From f32b1d412dfbcd55b409a3b4a5844aaf17d3ffbc Mon Sep 17 00:00:00 2001 From: Luoyl233 Date: Fri, 1 Jun 2018 21:38:27 +0800 Subject: [PATCH] Add project --- lab1/Makefile | 15 ++ lab1/app/Makefile | 7 + lab1/app/app.s | 73 ++++++++++ lab1/bootloader/Makefile | 9 ++ lab1/bootloader/boot.c | 31 ++++ lab1/bootloader/boot.h | 25 ++++ lab1/bootloader/start.s | 43 ++++++ lab1/utils/genboot.pl | 19 +++ lab2/Makefile | 19 +++ lab2/app/.main.c.swp | Bin 0 -> 12288 bytes lab2/app/Makefile | 17 +++ lab2/app/main.c | 30 ++++ lab2/bootloader/Makefile | 20 +++ lab2/bootloader/boot.c | 55 ++++++++ lab2/bootloader/boot.h | 59 ++++++++ lab2/bootloader/start.S | 37 +++++ lab2/kernel/Makefile | 20 +++ lab2/kernel/include/common.h | 8 ++ lab2/kernel/include/common/assert.h | 10 ++ lab2/kernel/include/common/const.h | 9 ++ lab2/kernel/include/common/types.h | 15 ++ lab2/kernel/include/device.h | 6 + lab2/kernel/include/device/serial.h | 8 ++ lab2/kernel/include/x86.h | 12 ++ lab2/kernel/include/x86/cpu.h | 32 +++++ lab2/kernel/include/x86/io.h | 56 ++++++++ lab2/kernel/include/x86/irq.h | 8 ++ lab2/kernel/include/x86/memory.h | 111 +++++++++++++++ lab2/kernel/kernel/doIrq.S | 29 ++++ lab2/kernel/kernel/i8259.c | 26 ++++ lab2/kernel/kernel/idt.c | 56 ++++++++ lab2/kernel/kernel/irqHandle.c | 79 +++++++++++ lab2/kernel/kernel/kvm.c | 109 ++++++++++++++ lab2/kernel/kernel/serial.c | 31 ++++ lab2/kernel/lib/abort.c | 42 ++++++ lab2/kernel/main.c | 15 ++ lab2/lab2.zip | Bin 0 -> 16608 bytes lab2/lib/lib.h | 6 + lab2/lib/syscall.c | 120 ++++++++++++++++ lab2/lib/types.h | 17 +++ lab2/utils/genBoot.pl | 19 +++ lab2/utils/genKernel.pl | 13 ++ lab3/Makefile | 19 +++ lab3/app/Makefile | 17 +++ lab3/app/main.c | 30 ++++ lab3/bootloader/Makefile | 20 +++ lab3/bootloader/boot.c | 55 ++++++++ lab3/bootloader/boot.h | 59 ++++++++ lab3/bootloader/start.S | 37 +++++ lab3/kernel/Makefile | 20 +++ lab3/kernel/include/common.h | 8 ++ lab3/kernel/include/common/assert.h | 10 ++ lab3/kernel/include/common/const.h | 9 ++ lab3/kernel/include/common/types.h | 15 ++ lab3/kernel/include/device.h | 6 + lab3/kernel/include/device/serial.h | 8 ++ lab3/kernel/include/x86.h | 13 ++ lab3/kernel/include/x86/cpu.h | 32 +++++ lab3/kernel/include/x86/debug.h | 29 ++++ lab3/kernel/include/x86/io.h | 56 ++++++++ lab3/kernel/include/x86/irq.h | 8 ++ lab3/kernel/include/x86/memory.h | 151 ++++++++++++++++++++ lab3/kernel/kernel/debug.c | 78 ++++++++++ lab3/kernel/kernel/doIrq.S | 50 +++++++ lab3/kernel/kernel/i8259.c | 26 ++++ lab3/kernel/kernel/idle.c | 95 +++++++++++++ lab3/kernel/kernel/idt.c | 58 ++++++++ lab3/kernel/kernel/irqHandle.c | 194 +++++++++++++++++++++++++ lab3/kernel/kernel/kvm.c | 117 +++++++++++++++ lab3/kernel/kernel/schedule.c | 33 +++++ lab3/kernel/kernel/serial.c | 24 ++++ lab3/kernel/kernel/timer.c | 12 ++ lab3/kernel/lib/abort.c | 42 ++++++ lab3/kernel/main.c | 30 ++++ lab3/lib/lib.h | 11 ++ lab3/lib/syscall.c | 152 ++++++++++++++++++++ lab3/lib/types.h | 17 +++ lab3/utils/genBoot.pl | 19 +++ lab3/utils/genKernel.pl | 13 ++ lab4/Makefile | 19 +++ lab4/app/Makefile | 17 +++ lab4/app/main.c | 43 ++++++ lab4/bootloader/Makefile | 20 +++ lab4/bootloader/boot.c | 55 ++++++++ lab4/bootloader/boot.h | 59 ++++++++ lab4/bootloader/start.S | 37 +++++ lab4/kernel/Makefile | 20 +++ lab4/kernel/include/common.h | 8 ++ lab4/kernel/include/common/assert.h | 10 ++ lab4/kernel/include/common/const.h | 9 ++ lab4/kernel/include/common/types.h | 15 ++ lab4/kernel/include/device.h | 6 + lab4/kernel/include/device/serial.h | 8 ++ lab4/kernel/include/x86.h | 13 ++ lab4/kernel/include/x86/cpu.h | 32 +++++ lab4/kernel/include/x86/debug.h | 29 ++++ lab4/kernel/include/x86/io.h | 56 ++++++++ lab4/kernel/include/x86/irq.h | 8 ++ lab4/kernel/include/x86/memory.h | 177 +++++++++++++++++++++++ lab4/kernel/kernel/debug.c | 78 ++++++++++ lab4/kernel/kernel/doIrq.S | 50 +++++++ lab4/kernel/kernel/i8259.c | 26 ++++ lab4/kernel/kernel/idle.c | 98 +++++++++++++ lab4/kernel/kernel/idt.c | 58 ++++++++ lab4/kernel/kernel/irqHandle.c | 212 ++++++++++++++++++++++++++++ lab4/kernel/kernel/kvm.c | 117 +++++++++++++++ lab4/kernel/kernel/pv.c | 131 +++++++++++++++++ lab4/kernel/kernel/schedule.c | 36 +++++ lab4/kernel/kernel/serial.c | 24 ++++ lab4/kernel/kernel/timer.c | 12 ++ lab4/kernel/lib/abort.c | 42 ++++++ lab4/kernel/main.c | 30 ++++ lab4/lib/lib.h | 25 ++++ lab4/lib/syscall.c | 185 ++++++++++++++++++++++++ lab4/lib/types.h | 17 +++ lab4/utils/genBoot.pl | 19 +++ lab4/utils/genKernel.pl | 13 ++ 117 files changed, 4703 insertions(+) create mode 100644 lab1/Makefile create mode 100644 lab1/app/Makefile create mode 100644 lab1/app/app.s create mode 100644 lab1/bootloader/Makefile create mode 100644 lab1/bootloader/boot.c create mode 100644 lab1/bootloader/boot.h create mode 100644 lab1/bootloader/start.s create mode 100644 lab1/utils/genboot.pl create mode 100644 lab2/Makefile create mode 100644 lab2/app/.main.c.swp create mode 100644 lab2/app/Makefile create mode 100644 lab2/app/main.c create mode 100644 lab2/bootloader/Makefile create mode 100644 lab2/bootloader/boot.c create mode 100644 lab2/bootloader/boot.h create mode 100644 lab2/bootloader/start.S create mode 100644 lab2/kernel/Makefile create mode 100644 lab2/kernel/include/common.h create mode 100644 lab2/kernel/include/common/assert.h create mode 100644 lab2/kernel/include/common/const.h create mode 100644 lab2/kernel/include/common/types.h create mode 100644 lab2/kernel/include/device.h create mode 100644 lab2/kernel/include/device/serial.h create mode 100644 lab2/kernel/include/x86.h create mode 100644 lab2/kernel/include/x86/cpu.h create mode 100644 lab2/kernel/include/x86/io.h create mode 100644 lab2/kernel/include/x86/irq.h create mode 100644 lab2/kernel/include/x86/memory.h create mode 100644 lab2/kernel/kernel/doIrq.S create mode 100644 lab2/kernel/kernel/i8259.c create mode 100644 lab2/kernel/kernel/idt.c create mode 100644 lab2/kernel/kernel/irqHandle.c create mode 100644 lab2/kernel/kernel/kvm.c create mode 100644 lab2/kernel/kernel/serial.c create mode 100644 lab2/kernel/lib/abort.c create mode 100644 lab2/kernel/main.c create mode 100644 lab2/lab2.zip create mode 100644 lab2/lib/lib.h create mode 100644 lab2/lib/syscall.c create mode 100644 lab2/lib/types.h create mode 100644 lab2/utils/genBoot.pl create mode 100644 lab2/utils/genKernel.pl create mode 100644 lab3/Makefile create mode 100644 lab3/app/Makefile create mode 100644 lab3/app/main.c create mode 100644 lab3/bootloader/Makefile create mode 100644 lab3/bootloader/boot.c create mode 100644 lab3/bootloader/boot.h create mode 100644 lab3/bootloader/start.S create mode 100644 lab3/kernel/Makefile create mode 100644 lab3/kernel/include/common.h create mode 100644 lab3/kernel/include/common/assert.h create mode 100644 lab3/kernel/include/common/const.h create mode 100644 lab3/kernel/include/common/types.h create mode 100644 lab3/kernel/include/device.h create mode 100644 lab3/kernel/include/device/serial.h create mode 100644 lab3/kernel/include/x86.h create mode 100644 lab3/kernel/include/x86/cpu.h create mode 100644 lab3/kernel/include/x86/debug.h create mode 100644 lab3/kernel/include/x86/io.h create mode 100644 lab3/kernel/include/x86/irq.h create mode 100644 lab3/kernel/include/x86/memory.h create mode 100644 lab3/kernel/kernel/debug.c create mode 100644 lab3/kernel/kernel/doIrq.S create mode 100644 lab3/kernel/kernel/i8259.c create mode 100644 lab3/kernel/kernel/idle.c create mode 100644 lab3/kernel/kernel/idt.c create mode 100644 lab3/kernel/kernel/irqHandle.c create mode 100644 lab3/kernel/kernel/kvm.c create mode 100644 lab3/kernel/kernel/schedule.c create mode 100644 lab3/kernel/kernel/serial.c create mode 100644 lab3/kernel/kernel/timer.c create mode 100644 lab3/kernel/lib/abort.c create mode 100644 lab3/kernel/main.c create mode 100644 lab3/lib/lib.h create mode 100644 lab3/lib/syscall.c create mode 100644 lab3/lib/types.h create mode 100644 lab3/utils/genBoot.pl create mode 100644 lab3/utils/genKernel.pl create mode 100644 lab4/Makefile create mode 100644 lab4/app/Makefile create mode 100644 lab4/app/main.c create mode 100644 lab4/bootloader/Makefile create mode 100644 lab4/bootloader/boot.c create mode 100644 lab4/bootloader/boot.h create mode 100644 lab4/bootloader/start.S create mode 100644 lab4/kernel/Makefile create mode 100644 lab4/kernel/include/common.h create mode 100644 lab4/kernel/include/common/assert.h create mode 100644 lab4/kernel/include/common/const.h create mode 100644 lab4/kernel/include/common/types.h create mode 100644 lab4/kernel/include/device.h create mode 100644 lab4/kernel/include/device/serial.h create mode 100644 lab4/kernel/include/x86.h create mode 100644 lab4/kernel/include/x86/cpu.h create mode 100644 lab4/kernel/include/x86/debug.h create mode 100644 lab4/kernel/include/x86/io.h create mode 100644 lab4/kernel/include/x86/irq.h create mode 100644 lab4/kernel/include/x86/memory.h create mode 100644 lab4/kernel/kernel/debug.c create mode 100644 lab4/kernel/kernel/doIrq.S create mode 100644 lab4/kernel/kernel/i8259.c create mode 100644 lab4/kernel/kernel/idle.c create mode 100644 lab4/kernel/kernel/idt.c create mode 100644 lab4/kernel/kernel/irqHandle.c create mode 100644 lab4/kernel/kernel/kvm.c create mode 100644 lab4/kernel/kernel/pv.c create mode 100644 lab4/kernel/kernel/schedule.c create mode 100644 lab4/kernel/kernel/serial.c create mode 100644 lab4/kernel/kernel/timer.c create mode 100644 lab4/kernel/lib/abort.c create mode 100644 lab4/kernel/main.c create mode 100644 lab4/lib/lib.h create mode 100644 lab4/lib/syscall.c create mode 100644 lab4/lib/types.h create mode 100644 lab4/utils/genBoot.pl create mode 100644 lab4/utils/genKernel.pl diff --git a/lab1/Makefile b/lab1/Makefile new file mode 100644 index 0000000..51361f6 --- /dev/null +++ b/lab1/Makefile @@ -0,0 +1,15 @@ +os.img: + cd bootloader; make bootloader.bin + cd app; make app.bin + cat bootloader/bootloader.bin app/app.bin > os.img + +clean: + cd bootloader; make clean + cd app; make clean + rm -f os.img + +play: + qemu-system-i386 os.img + +debug: + qemu-system-i386 -s -S os.img diff --git a/lab1/app/Makefile b/lab1/app/Makefile new file mode 100644 index 0000000..e116ceb --- /dev/null +++ b/lab1/app/Makefile @@ -0,0 +1,7 @@ +app.bin: app.s + gcc -c -m32 app.s -o app.o + ld -m elf_i386 -e start -Ttext 0x8c00 app.o -o app.elf + objcopy -S -j .text -O binary app.elf app.bin + +clean: + rm -rf *.o *.elf *.bin diff --git a/lab1/app/app.s b/lab1/app/app.s new file mode 100644 index 0000000..30a9486 --- /dev/null +++ b/lab1/app/app.s @@ -0,0 +1,73 @@ +.code32 + +.global start +start: + + movl $((80*5+0)*2), %edi #在第5行第0列打印 + movb $0x0c, %ah #黑底红字 + movb $0x48, %al #0x48为H的ASCII码 + movw %ax, %gs:(%edi) #写显存 + + movl $((80*5+1)*2), %edi + movb $0x0c, %ah + movb $0x65, %al + movw %ax, %gs:(%edi) + + movl $((80*5+2)*2), %edi + movb $0x0c, %ah + movb $0x6c, %al + movw %ax, %gs:(%edi) + + movl $((80*5+3)*2), %edi + movb $0x0c, %ah + movb $0x6c, %al + movw %ax, %gs:(%edi) + + movl $((80*5+4)*2), %edi + movb $0x0c, %ah + movb $0x6f, %al + movw %ax, %gs:(%edi) + + movl $((80*5+5)*2), %edi + movb $0x0c, %ah + movb $0x2c, %al + movw %ax, %gs:(%edi) + + movl $((80*5+6)*2), %edi + movb $0x0c, %ah + movb $0x20, %al + movw %ax, %gs:(%edi) + + movl $((80*5+7)*2), %edi + movb $0x0c, %ah + movb $0x57, %al + movw %ax, %gs:(%edi) + + movl $((80*5+8)*2), %edi + movb $0x0c, %ah + movb $0x6f, %al + movw %ax, %gs:(%edi) + + movl $((80*5+9)*2), %edi + movb $0x0c, %ah + movb $0x72, %al + movw %ax, %gs:(%edi) + + movl $((80*5+10)*2), %edi + movb $0x0c, %ah + movb $0x6c, %al + movw %ax, %gs:(%edi) + + movl $((80*5+11)*2), %edi + movb $0x0c, %ah + movb $0x64, %al + movw %ax, %gs:(%edi) + + movl $((80*5+12)*2), %edi + movb $0x0c, %ah + movb $0x21, %al + movw %ax, %gs:(%edi) + +loop: + jmp loop + diff --git a/lab1/bootloader/Makefile b/lab1/bootloader/Makefile new file mode 100644 index 0000000..ec8a7f1 --- /dev/null +++ b/lab1/bootloader/Makefile @@ -0,0 +1,9 @@ +bootloader.bin: start.s boot.c boot.h + gcc -c -m32 start.s -o start.o + gcc -c -m32 -O1 -fno-stack-protector boot.c -o boot.o + ld -m elf_i386 -e start -Ttext 0x7c00 start.o boot.o -o bootloader.elf + objcopy -S -j .text -O binary bootloader.elf bootloader.bin + ../utils/genboot.pl bootloader.bin + +clean: + rm -rf *.o *.elf *.bin diff --git a/lab1/bootloader/boot.c b/lab1/bootloader/boot.c new file mode 100644 index 0000000..0d4e682 --- /dev/null +++ b/lab1/bootloader/boot.c @@ -0,0 +1,31 @@ +#include "boot.h" + +#define SECTSIZE 512 + +void bootMain(void) { + void (*elf)(void); + // loading sector 1 to memory + readSect((void *)0x8c00, 1); + elf = (void *)0x8c00; + elf(); +} + +void waitDisk(void) { // waiting for disk + while((inByte(0x1F7) & 0xC0) != 0x40); +} + +void readSect(void *dst, int offset) { // reading one sector of disk + int i; + waitDisk(); + outByte(0x1F2, 1); + outByte(0x1F3, offset); + outByte(0x1F4, offset >> 8); + outByte(0x1F5, offset >> 16); + outByte(0x1F6, (offset >> 24) | 0xE0); + outByte(0x1F7, 0x20); + + waitDisk(); + for (i = 0; i < SECTSIZE / 4; i ++) { + ((int *)dst)[i] = inLong(0x1F0); + } +} diff --git a/lab1/bootloader/boot.h b/lab1/bootloader/boot.h new file mode 100644 index 0000000..d4f383c --- /dev/null +++ b/lab1/bootloader/boot.h @@ -0,0 +1,25 @@ +#ifndef BOOT_H +#define BOOT_H + +void waitDisk(void); + +void readSect(void *dst, int offset); + +/* I/O functions */ +static inline char inByte(short port) { + char data; + asm volatile("in %1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static inline int inLong(short port) { + int data; + asm volatile("in %1, %0" : "=a" (data) : "d" (port)); + return data; +} + +static inline void outByte(short port, char data) { + asm volatile("out %0,%1" : : "a" (data), "d" (port)); +} + +#endif diff --git a/lab1/bootloader/start.s b/lab1/bootloader/start.s new file mode 100644 index 0000000..85a41b8 --- /dev/null +++ b/lab1/bootloader/start.s @@ -0,0 +1,43 @@ +.code16 + +.global start +start: + cli #关闭中断 + inb $0x92, %al #启动A20总线 + orb $0x02, %al + outb %al, $0x92 + data32 addr32 lgdt gdtDesc #加载GDTR + movl %cr0, %eax #启动保护模式 + orb $0x01, %al + movl %eax, %cr0 + data32 ljmp $0x08, $start32 #长跳转切换至保护 + +.code32 +start32: + movw $0x18, %ax + movw %ax, %gs + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %ss + movl $(128<<20), %esp + jmp bootMain + +.p2align 2 +gdt: + .word 0,0 # empty entry + .byte 0,0,0,0 + + .word 0xffff,0 + .byte 0,0x9a,0xcf,0 + + .word 0xffff,0 + .byte 0,0x92,0xcf,0 + + .word 0xffff,0x8000 + .byte 0x0b,0x92,0xcf,0 + +gdtDesc: + .word (gdtDesc - gdt -1) + .long gdt diff --git a/lab1/utils/genboot.pl b/lab1/utils/genboot.pl new file mode 100644 index 0000000..5bc39bc --- /dev/null +++ b/lab1/utils/genboot.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 1000); + +if($n > 510){ + print STDERR "ERROR: boot block too large: $n bytes (max 510)\n"; + exit 1; +} + +print STDERR "OK: boot block is $n bytes (max 510)\n"; + +$buf .= "\0" x (510-$n); +$buf .= "\x55\xAA"; + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/lab2/Makefile b/lab2/Makefile new file mode 100644 index 0000000..1b2eaa5 --- /dev/null +++ b/lab2/Makefile @@ -0,0 +1,19 @@ +QEMU = qemu-system-i386 + +os.img: + @cd bootloader; make + @cd kernel; make + @cd app; make + cat bootloader/bootloader.bin kernel/kMain.elf app/uMain.elf > os.img + +play: os.img + $(QEMU) -serial stdio os.img + +debug: os.img + $(QEMU) -serial stdio -s -S os.img + +clean: + @cd bootloader; make clean + @cd kernel; make clean + @cd app; make clean + rm -f os.img diff --git a/lab2/app/.main.c.swp b/lab2/app/.main.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..72cc0f0a00aa18283f213549d4aa060ae6b3f6dc GIT binary patch literal 12288 zcmeI2&yU+g6vwCB0+gaw96>LM!e-mVaenQ(TdjmDRqY;14+VroRj}hpW9`Hf#dfn% z)ruoG{t0fqmp_5tL0sqsap8dA&ZT^xy-Ty+!$JxN(0j>uJho@Po_zeC4@m;|qrIE7 z?F64_rA%g*hL4{TS&+pk#-A3Ca>I^II>rxr9e+0KO#LW!MyE}b z^Flxfyc~fn9k;!+s^9Cn^;(rKod59U{A9Ke5CTF#2nYcoAOwVf5D)_YIRfeIjCzh$ zzXH7jojDXX5<)--2mv7=1cZPP5CTF#2nYcoAOwWK|Ac@aDs`ix)OQg7{?Fe5{B};M zXV4GOQ|KG$E9i4*2m1XDr84L`^fvV6S*7+M2m1MSr5-~|=*eqJeF5EtEIxenyie$#@}^5Lr`^LV(8Z&@+#l=WH^%U$ z*Kg5axRv)X5Z%>fzHb+_M~lc9N*VpqW^*bi@6a*ikE-w0JI%ZAUTkiDdg(LR!fD&P z?6!BEJdTgv+n7>1(bP!Dj?p^Ya}RRbMaLmvt_3z+@|MTm^QW5oSFKG0V@LaBtRE&c z)s))YZK|hszNDE=qBOEGtoc?Qbn{z-nSLD7O@CjHky+%M1hcd;g~P;8iC2XUUkv{K zNsm=DjnUDo%1hn2wSnd~H-;OZn_%PEj0B&uk&G->+!)zL!k^{_R$yD)V=c5{uN0GO z$BC_%(YvLT&hMWeCks8_DV?gX7bTZGt&n-Wm4w3XaLe_)J2A?p&1KQ+4z>qge`|o+ zXm_v^C!a|)_7@y_ixSXdwU0Th*mA-!`1y>Sqz5M&r041@S zPDSPrQYOzR)WEIV_=9>iPh-wuE*>tgqv9#eU+;d`ONiOLNGM7sHZvgwx|~|Y1EY9? x1o|HSI`24zjlyG{vTJcVUpDXCDBPq6O4XxyWU^4B?3Xj0IFs7SArl3B;195&)#?BM literal 0 HcmV?d00001 diff --git a/lab2/app/Makefile b/lab2/app/Makefile new file mode 100644 index 0000000..259f8bf --- /dev/null +++ b/lab2/app/Makefile @@ -0,0 +1,17 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 -I../lib +LDFLAGS = -m elf_i386 + +UCFILES = $(shell find ./ -name "*.c") +LCFILES = $(shell find ../lib -name "*.c") +UOBJS = $(UCFILES:.c=.o) $(LCFILES:.c=.o) + +umain.bin: $(UOBJS) + $(LD) $(LDFLAGS) -e uEntry -Ttext 0x00200000 -o uMain.elf $(UOBJS) + +clean: + rm -rf $(UOBJS) uMain.elf diff --git a/lab2/app/main.c b/lab2/app/main.c new file mode 100644 index 0000000..c9c6619 --- /dev/null +++ b/lab2/app/main.c @@ -0,0 +1,30 @@ +#include "lib.h" +#include "types.h" + +int uEntry(void) { + + printf("printf test begin...\n"); + printf("the answer should be:\n"); + printf("#######################################################\n"); + printf("Hello, welcome to OSlab! I'm the body of the game. "); + printf("Bootblock loads me to the memory position of 0x100000, and Makefile also tells me that I'm at the location of 0x100000. "); + printf("~!@#/(^&*()_+`1234567890-=...... "); + printf("Now I will test your printf: "); + printf("1 + 1 = 2, 123 * 456 = 56088\n0, -1, -2147483648, -1412505855, -32768, 102030\n0, ffffffff, 80000000, abcdef01, ffff8000, 18e8e\n"); + printf("#######################################################\n"); + printf("your answer:\n"); + printf("=======================================================\n"); + printf("%s %s%scome %co%s", "Hello,", "", "wel", 't', " "); + printf("%c%c%c%c%c! ", 'O', 'S', 'l', 'a', 'b'); + printf("I'm the %s of %s. %s 0x%x, %s 0x%x. ", "body", "the game", "Bootblock loads me to the memory position of", 0x100000, "and Makefile also tells me that I'm at the location of", 0x100000); + printf("~!@#/(^&*()_+`1234567890-=...... "); + printf("Now I will test your printf: "); + printf("%d + %d = %d, %d * %d = %d\n", 1, 1, 1 + 1, 123, 456, 123 * 456); + printf("%d, %d, %d, %d, %d, %d\n", 0, 0xffffffff, 0x80000000, 0xabcedf01, -32768, 102030); + printf("%x, %x, %x, %x, %x, %x\n", 0, 0xffffffff, 0x80000000, 0xabcedf01, -32768, 102030); + printf("=======================================================\n"); + printf("Test end!!! Good luck!!!\n"); + + while(1); + return 0; +} diff --git a/lab2/bootloader/Makefile b/lab2/bootloader/Makefile new file mode 100644 index 0000000..76fa6e5 --- /dev/null +++ b/lab2/bootloader/Makefile @@ -0,0 +1,20 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 +ASFLAGS = -m32 +LDFLAGS = -m elf_i386 + +BSFILES = $(shell find ./ -name "*.S") +BCFILES = $(shell find ./ -name "*.c") +BOBJS = $(BSFILES:.S=.o) $(BCFILES:.c=.o) + +bootloader.bin: $(BOBJS) + $(LD) $(LDFLAGS) -e start -Ttext 0x7c00 -o bootloader.elf $(BOBJS) + objcopy -O binary bootloader.elf bootloader.bin + @../utils/genBoot.pl bootloader.bin + +clean: + rm -rf $(BOBJS) bootloader.elf bootloader.bin diff --git a/lab2/bootloader/boot.c b/lab2/bootloader/boot.c new file mode 100644 index 0000000..430e957 --- /dev/null +++ b/lab2/bootloader/boot.c @@ -0,0 +1,55 @@ +#include "boot.h" +#include + +#define SECTSIZE 512 +#define MAXNUM 200 +#define BUFSIZE (SECTSIZE*MAXNUM) + +#define NULL ((void *)0) + +void bootMain(void) { + /* 加载内核至内存,并跳转执行 */ + void (*kernel) (void); + + ELFHeader *elf; + ProgramHeader *ph; + + unsigned char buf[BUFSIZE]; + + int i=0; + for(i=0; i < MAXNUM; i++) + readSect((void *)(buf + i*SECTSIZE), i+1); + + elf = (void *)buf; + for(i=0; i < elf->phnum; i++){ + ph = (ProgramHeader *)(buf + elf->phoff + i * elf->phentsize); + int vaddr = ph->vaddr; + int filesz = ph->filesz; + memcpy((void *)vaddr, buf+ph->off, filesz); + memset((void *)(vaddr+filesz), 0, ph->memsz-filesz); + } + kernel = (void *)elf->entry; + kernel(); +} + +void waitDisk(void) { // waiting for disk + while((inByte(0x1F7) & 0xC0) != 0x40); +} + +void readSect(void *dst, int offset) { // reading a sector of disk + int i; + waitDisk(); + outByte(0x1F2, 1); + outByte(0x1F3, offset); + outByte(0x1F4, offset >> 8); + outByte(0x1F5, offset >> 16); + outByte(0x1F6, (offset >> 24) | 0xE0); + outByte(0x1F7, 0x20); + + waitDisk(); + for (i = 0; i < SECTSIZE / 4; i ++) { + ((int *)dst)[i] = inLong(0x1F0); + } +} + + diff --git a/lab2/bootloader/boot.h b/lab2/bootloader/boot.h new file mode 100644 index 0000000..b313576 --- /dev/null +++ b/lab2/bootloader/boot.h @@ -0,0 +1,59 @@ +#ifndef BOOT_H +#define BOOT_H + + +struct ELFHeader { + unsigned int magic; + unsigned char elf[12]; + unsigned short type; + unsigned short machine; + unsigned int version; + unsigned int entry; + unsigned int phoff; + unsigned int shoff; + unsigned int flags; + unsigned short ehsize; + unsigned short phentsize; + unsigned short phnum; + unsigned short shentsize; + unsigned short shnum; + unsigned short shstrndx; +}; + +/* ELF32 Program header */ +struct ProgramHeader { + unsigned int type; + unsigned int off; + unsigned int vaddr; + unsigned int paddr; + unsigned int filesz; + unsigned int memsz; + unsigned int flags; + unsigned int align; +}; + +typedef struct ELFHeader ELFHeader; +typedef struct ProgramHeader ProgramHeader; + +void waitDisk(void); + +void readSect(void *dst, int offset); + +/* I/O functions */ +static inline char inByte(short port) { + char data; + asm volatile("in %1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static inline int inLong(short port) { + int data; + asm volatile("in %1, %0" : "=a" (data) : "d" (port)); + return data; +} + +static inline void outByte(short port, char data) { + asm volatile("out %0,%1" : : "a" (data), "d" (port)); +} + +#endif diff --git a/lab2/bootloader/start.S b/lab2/bootloader/start.S new file mode 100644 index 0000000..7e340f2 --- /dev/null +++ b/lab2/bootloader/start.S @@ -0,0 +1,37 @@ +.code16 + +.global start +start: + cli #关闭中断 + inb $0x92, %al #启动A20总线 + orb $0x02, %al + outb %al, $0x92 + data32 addr32 lgdt gdtDesc #加载GDTR + movl %cr0, %eax #启动保护模式 + orb $0x01, %al + movl %eax, %cr0 + data32 ljmp $0x08, $start32 #长跳转切换至保护 + +.code32 +start32: + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movl $(128<<20), %esp + jmp bootMain + +.p2align 2 +gdt: # each table entry, at least 1 entry + .word 0,0 # empty entry + .byte 0,0,0,0 + + .word 0xffff,0 + .byte 0,0x9a,0xcf,0 + + .word 0xffff,0 + .byte 0,0x92,0xcf,0 + +gdtDesc: # 6 bytes in total + .word (gdtDesc - gdt -1) + .long gdt diff --git a/lab2/kernel/Makefile b/lab2/kernel/Makefile new file mode 100644 index 0000000..1dabd77 --- /dev/null +++ b/lab2/kernel/Makefile @@ -0,0 +1,20 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 -I./include +ASFLAGS = -m32 +LDFLAGS = -m elf_i386 + +KCFILES = $(shell find ./ -name "*.c") +KSFILES = $(shell find ./ -name "*.S") +KOBJS = $(KCFILES:.c=.o) $(KSFILES:.S=.o) + +kmain.bin: $(KOBJS) + $(LD) $(LDFLAGS) -e kEntry -Ttext 0x00100000 -o kMain.elf $(KOBJS) + @../utils/genKernel.pl kMain.elf + + +clean: + rm -rf $(KOBJS) kMain.elf kMain.bin diff --git a/lab2/kernel/include/common.h b/lab2/kernel/include/common.h new file mode 100644 index 0000000..f3f8b1d --- /dev/null +++ b/lab2/kernel/include/common.h @@ -0,0 +1,8 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "common/types.h" +#include "common/const.h" +#include "common/assert.h" + +#endif diff --git a/lab2/kernel/include/common/assert.h b/lab2/kernel/include/common/assert.h new file mode 100644 index 0000000..8c5e9bd --- /dev/null +++ b/lab2/kernel/include/common/assert.h @@ -0,0 +1,10 @@ +#ifndef __ASSERT_H__ +#define __ASSERT_H__ + +int abort(const char *, int); + +/* assert: 断言条件为真,若为假则蓝屏退出 */ +#define assert(cond) \ + ((cond) ? (0) : (abort(__FILE__, __LINE__))) + +#endif diff --git a/lab2/kernel/include/common/const.h b/lab2/kernel/include/common/const.h new file mode 100644 index 0000000..7a3f9eb --- /dev/null +++ b/lab2/kernel/include/common/const.h @@ -0,0 +1,9 @@ +#ifndef __CONST_H__ +#define __CONST_H__ + +#define TRUE 1 +#define FALSE 0 + +#define NULL ((void*)0) + +#endif diff --git a/lab2/kernel/include/common/types.h b/lab2/kernel/include/common/types.h new file mode 100644 index 0000000..ba71de2 --- /dev/null +++ b/lab2/kernel/include/common/types.h @@ -0,0 +1,15 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +/* 定义数据类型 */ +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned int size_t; + +#define PT_LOAD 1 + +#endif diff --git a/lab2/kernel/include/device.h b/lab2/kernel/include/device.h new file mode 100644 index 0000000..32dbdf2 --- /dev/null +++ b/lab2/kernel/include/device.h @@ -0,0 +1,6 @@ +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +#include "device/serial.h" + +#endif diff --git a/lab2/kernel/include/device/serial.h b/lab2/kernel/include/device/serial.h new file mode 100644 index 0000000..2c71d57 --- /dev/null +++ b/lab2/kernel/include/device/serial.h @@ -0,0 +1,8 @@ +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +void initSerial(void); +void putChar(char); +#define SERIAL_PORT 0x3F8 + +#endif diff --git a/lab2/kernel/include/x86.h b/lab2/kernel/include/x86.h new file mode 100644 index 0000000..45a8699 --- /dev/null +++ b/lab2/kernel/include/x86.h @@ -0,0 +1,12 @@ +#ifndef __X86_H__ +#define __X86_H__ + +#include "x86/cpu.h" +#include "x86/memory.h" +#include "x86/io.h" +#include "x86/irq.h" + +void initSeg(void); +void loadUMain(void); + +#endif diff --git a/lab2/kernel/include/x86/cpu.h b/lab2/kernel/include/x86/cpu.h new file mode 100644 index 0000000..744facd --- /dev/null +++ b/lab2/kernel/include/x86/cpu.h @@ -0,0 +1,32 @@ +#ifndef __X86_CPU_H__ +#define __X86_CPU_H__ + +#include "common.h" + +/* 将CPU置入休眠状态直到下次中断到来 */ +static inline void waitForInterrupt() { + asm volatile("hlt"); +} + +/* 修改IDTR */ +static inline void saveIdt(void *addr, uint32_t size) { + static volatile uint16_t data[3]; + data[0] = size - 1; + data[1] = (uint32_t)addr; + data[2] = ((uint32_t)addr) >> 16; + asm volatile("lidt (%0)" : : "r"(data)); +} + +/* 打开外部中断 */ +static inline void enableInterrupt(void) { + asm volatile("sti"); +} + +/* 关闭外部中断 */ +static inline void disableInterrupt(void) { + asm volatile("cli"); +} + +#define NR_IRQ 256 + +#endif diff --git a/lab2/kernel/include/x86/io.h b/lab2/kernel/include/x86/io.h new file mode 100644 index 0000000..5fad01e --- /dev/null +++ b/lab2/kernel/include/x86/io.h @@ -0,0 +1,56 @@ +#ifndef __X86_IO_H__ +#define __X86_IO_H__ +/* ELF32二进制文件头 */ +struct ELFHeader { + unsigned int magic; + unsigned char elf[12]; + unsigned short type; + unsigned short machine; + unsigned int version; + unsigned int entry; + unsigned int phoff; + unsigned int shoff; + unsigned int flags; + unsigned short ehsize; + unsigned short phentsize; + unsigned short phnum; + unsigned short shentsize; + unsigned short shnum; + unsigned short shstrndx; +}; + +/* ELF32 Program header */ +struct ProgramHeader { + unsigned int type; + unsigned int off; + unsigned int vaddr; + unsigned int paddr; + unsigned int filesz; + unsigned int memsz; + unsigned int flags; + unsigned int align; +}; + +typedef struct ELFHeader ELFHeader; +typedef struct ProgramHeader ProgramHeader; + + +static inline int inLong(short port) { + int data; + asm volatile("in %1, %0" : "=a" (data) : "d" (port)); + return data; +} + +/* 读I/O端口 */ +static inline uint8_t inByte(uint16_t port) { + uint8_t data; + asm volatile("in %1, %0" : "=a"(data) : "d"(port)); + return data; +} + +/* 写I/O端口 */ +static inline void outByte(uint16_t port, int8_t data) { + asm volatile("out %%al, %%dx" : : "a"(data), "d"(port)); +} + +#endif diff --git a/lab2/kernel/include/x86/irq.h b/lab2/kernel/include/x86/irq.h new file mode 100644 index 0000000..4d2c161 --- /dev/null +++ b/lab2/kernel/include/x86/irq.h @@ -0,0 +1,8 @@ +#ifndef __IRQ_H__ +#define __IRQ_H__ + +/* 中断处理相关函数 */ +void initIdt(void); +void initIntr(void); + +#endif diff --git a/lab2/kernel/include/x86/memory.h b/lab2/kernel/include/x86/memory.h new file mode 100644 index 0000000..eb7b20e --- /dev/null +++ b/lab2/kernel/include/x86/memory.h @@ -0,0 +1,111 @@ +#ifndef __X86_MEMORY_H__ +#define __X86_MEMORY_H__ + +#define DPL_KERN 0 +#define DPL_USER 3 + +// Application segment type bits +#define STA_X 0x8 // Executable segment +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) + +// System segment type bits +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate + +// GDT entries +#define NR_SEGMENTS 7 // GDT size +#define SEG_KCODE 1 // Kernel code +#define SEG_KDATA 2 // Kernel data/stack +#define SEG_UCODE 3 // User code +#define SEG_UDATA 4 // User data/stack +#define SEG_TSS 5 // Global unique task state segement + +// Selectors +#define KSEL(desc) (((desc) << 3) | DPL_KERN) +#define USEL(desc) (((desc) << 3) | DPL_USER) + +struct GateDescriptor { + uint32_t offset_15_0 : 16; + uint32_t segment : 16; + uint32_t pad0 : 8; + uint32_t type : 4; + uint32_t system : 1; + uint32_t privilege_level : 2; + uint32_t present : 1; + uint32_t offset_31_16 : 16; +}; + +typedef struct GateDescriptor GateDescriptor; + +struct TrapFrame { + uint32_t edi, esi, ebp, xxx, ebx, edx, ecx, eax; + int32_t irq; +}; + +/* +1. The number of bits in a bit field sets the limit to the range of values it can hold +2. Multiple adjacent bit fields are usually packed together (although this behavior is implementation-defined) + +Refer: en.cppreference.com/w/cpp/language/bit_field +*/ +struct SegDesc { + uint32_t lim_15_0 : 16; // Low bits of segment limit + uint32_t base_15_0 : 16; // Low bits of segment base address + uint32_t base_23_16 : 8; // Middle bits of segment base address + uint32_t type : 4; // Segment type (see STS_ constants) + uint32_t s : 1; // 0 = system, 1 = application + uint32_t dpl : 2; // Descriptor Privilege Level + uint32_t p : 1; // Present + uint32_t lim_19_16 : 4; // High bits of segment limit + uint32_t avl : 1; // Unused (available for software use) + uint32_t rsv1 : 1; // Reserved + uint32_t db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + uint32_t g : 1; // Granularity: limit scaled by 4K when set + uint32_t base_31_24 : 8; // High bits of segment base address +}; +typedef struct SegDesc SegDesc; + +#define SEG(type, base, lim, dpl) (SegDesc) \ +{ ((lim) >> 12) & 0xffff, (uint32_t)(base) & 0xffff, \ + ((uint32_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uint32_t)(lim) >> 28, 0, 0, 1, 1, (uint32_t)(base) >> 24 } + +#define SEG16(type, base, lim, dpl) (SegDesc) \ +{ (lim) & 0xffff, (uint32_t)(base) & 0xffff, \ + ((uint32_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \ + (uint32_t)(lim) >> 16, 0, 0, 1, 0, (uint32_t)(base) >> 24 } + +// Task state segment format +struct TSS { + uint32_t link; // old ts selector + uint32_t esp0; // Ring 0 Stack pointer and segment selector + uint32_t ss0; // after an increase in privilege level + union{ + struct{ + char dontcare[88]; + }; + struct{ + uint32_t esp1,ss1,esp2,ss2; + uint32_t cr3, eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; + uint32_t es, cs, ss, ds, fs, gs, ldt; + }; + }; +}; +typedef struct TSS TSS; + +static inline void setGdt(SegDesc *gdt, uint32_t size) { + volatile static uint16_t data[3]; + data[0] = size - 1; + data[1] = (uint32_t)gdt; + data[2] = (uint32_t)gdt >> 16; + asm volatile("lgdt (%0)" : : "r"(data)); +} + +static inline void lLdt(uint16_t sel) +{ + asm volatile("lldt %0" :: "r"(sel)); +} + +#endif diff --git a/lab2/kernel/kernel/doIrq.S b/lab2/kernel/kernel/doIrq.S new file mode 100644 index 0000000..92672dc --- /dev/null +++ b/lab2/kernel/kernel/doIrq.S @@ -0,0 +1,29 @@ +.code32 + +.global irqEmpty +irqEmpty: + pushl $0 // push dummy error code + pushl $-1 // push interrupt vector into kernel + jmp asmDoIrq + +.global irqGProtectFault +irqGProtectFault: + pushl $0xd + jmp asmDoIrq + +.global irqSyscall +irqSyscall: + pushl $0 // push dummy error code + pushl $0x80 // push interrupt vector into kernel stack + jmp asmDoIrq + +.global asmDoIrq +asmDoIrq: + pushal // push process state into kernel stack + pushl %esp + call irqHandle + addl $4, %esp + popal + addl $4, %esp //interrupt vector is on top of kernel stack + addl $4, %esp //error code is on top of kernel stack + iret diff --git a/lab2/kernel/kernel/i8259.c b/lab2/kernel/kernel/i8259.c new file mode 100644 index 0000000..7e50866 --- /dev/null +++ b/lab2/kernel/kernel/i8259.c @@ -0,0 +1,26 @@ +#include "x86.h" + +#define PORT_PIC_MASTER 0x20 +#define PORT_PIC_SLAVE 0xA0 +#define IRQ_SLAVE 2 + +/* 初始化8259中断控制器: + * 硬件中断IRQ从32号开始,自动发送EOI */ +void +initIntr(void) { + outByte(PORT_PIC_MASTER + 1, 0xFF); + outByte(PORT_PIC_SLAVE + 1 , 0xFF); + outByte(PORT_PIC_MASTER, 0x11); // Initialization command + outByte(PORT_PIC_MASTER + 1, 32); // Interrupt Vector Offset 0x20 + outByte(PORT_PIC_MASTER + 1, 1 << 2); // Tell Master PIC that there is a slave + outByte(PORT_PIC_MASTER + 1, 0x3); // Auto EOI in 8086/88 mode + outByte(PORT_PIC_SLAVE, 0x11); // Initialization command + outByte(PORT_PIC_SLAVE + 1, 32 + 8); // Interrupt Vector Offset 0x28 + outByte(PORT_PIC_SLAVE + 1, 2); // Tell Slave PIC its cascade identity + outByte(PORT_PIC_SLAVE + 1, 0x3); // Auto EOI in 8086/88 mode + + outByte(PORT_PIC_MASTER, 0x68); + outByte(PORT_PIC_MASTER, 0x0A); + outByte(PORT_PIC_SLAVE, 0x68); + outByte(PORT_PIC_SLAVE, 0x0A); +} diff --git a/lab2/kernel/kernel/idt.c b/lab2/kernel/kernel/idt.c new file mode 100644 index 0000000..072bf0d --- /dev/null +++ b/lab2/kernel/kernel/idt.c @@ -0,0 +1,56 @@ +#include "x86.h" +#include "device.h" + +#define INTERRUPT_GATE_32 0xE +#define TRAP_GATE_32 0xF + +/* IDT表的内容 */ +struct GateDescriptor idt[NR_IRQ]; // NR_IRQ=256, defined in x86/cpu.h + +/* 初始化一个中断门(interrupt gate) */ +static void setIntr(struct GateDescriptor *ptr, uint32_t selector, uint32_t offset, uint32_t dpl) { + ptr->offset_15_0 = offset & 0xFFFF; + ptr->segment = selector << 3; + ptr->pad0 = 0; + ptr->type = INTERRUPT_GATE_32; + ptr->system = FALSE; + ptr->privilege_level = dpl; + ptr->present = TRUE; + ptr->offset_31_16 = (offset >> 16) & 0xFFFF; +} + +/* 初始化一个陷阱门(trap gate) */ +static void setTrap(struct GateDescriptor *ptr, uint32_t selector, uint32_t offset, uint32_t dpl) { + ptr->offset_15_0 = offset & 0xFFFF; + ptr->segment = selector << 3; + ptr->pad0 = 0; + ptr->type = TRAP_GATE_32; + ptr->system = FALSE; + ptr->privilege_level = dpl; + ptr->present = TRUE; + ptr->offset_31_16 = (offset >> 16) & 0xFFFF; +} + +/* 声明函数,这些函数在汇编代码里定义 */ +void irqEmpty(); +void irqGProtectFault(); +void irqSyscall(); + +void initIdt() { + int i; + /* 为了防止系统异常终止,所有irq都有处理函数(irqEmpty)。 */ + for (i = 0; i < NR_IRQ; i ++) { + setTrap(idt + i, SEG_KCODE, (uint32_t)irqEmpty, DPL_KERN); + } + /* + * init your idt here + * 初始化 IDT 表, 为中断设置中断处理函数 + */ + + setTrap(idt + 0xd, SEG_KCODE, (uint32_t)irqGProtectFault, DPL_KERN); + + setIntr(idt + 0x80, SEG_KCODE, (uint32_t)irqSyscall, DPL_USER); // for int 0x80, interrupt vector is 0x80, Interruption is disabled + + /* 写入IDT */ + saveIdt(idt, sizeof(idt)); +} diff --git a/lab2/kernel/kernel/irqHandle.c b/lab2/kernel/kernel/irqHandle.c new file mode 100644 index 0000000..05301d1 --- /dev/null +++ b/lab2/kernel/kernel/irqHandle.c @@ -0,0 +1,79 @@ +#include "x86.h" +#include "device.h" + +#define SYS_WRITE 4 + +#define G_PORT (0xb800) + +void syscallHandle(struct TrapFrame *tf); + +void GProtectFaultHandle(struct TrapFrame *tf); + +int puts(char *, int); + +void irqHandle(struct TrapFrame *tf) { + /* + * 中断处理程序 + */ + /* Reassign segment register */ + + switch(tf->irq) { + case -1: + break; + case 0xd: + GProtectFaultHandle(tf); + break; + case 0x80: + syscallHandle(tf); + break; + default:assert(0); + } +} + +static void sys_write(struct TrapFrame *tf) +{ + int fd = (tf->ebx); + char *buf = (char *)(tf->ecx); + int len = tf->edx; + if(fd == 1) + puts(buf, len); + else + assert(0); +} + + +void syscallHandle(struct TrapFrame *tf) { + /* 实现系统调用*/ + switch(tf->eax){ + case SYS_WRITE: sys_write(tf); break; + default: assert(0); + } + +} + +void GProtectFaultHandle(struct TrapFrame *tf){ + assert(0); + return; +} + + +int puts(char *buf, int len) +{ + char *p1 = (char *)0xb8000; + char *p2 = buf; + static int off = 640; + int i; + for(i=0; i < len; i++){ + if(*p2 == '\n'){ + off = (off/160+1)*160; + p2 ++; + } + else{ + *(p1+off) = *(p2++); + *(p1+off+1) = 0x0c; + off += 2; + } + } + return p2-buf; + +} diff --git a/lab2/kernel/kernel/kvm.c b/lab2/kernel/kernel/kvm.c new file mode 100644 index 0000000..0eab66d --- /dev/null +++ b/lab2/kernel/kernel/kvm.c @@ -0,0 +1,109 @@ +#include "x86.h" +#include "device.h" +#include + +SegDesc gdt[NR_SEGMENTS]; +TSS tss; + +#define SECTSIZE 512 +#define NUM 200 +#define BUFSIZE (SECTSIZE*NUM) + +void waitDisk(void) { + while((inByte(0x1F7) & 0xC0) != 0x40); +} + +void readSect(void *dst, int offset) { + int i; + waitDisk(); + + outByte(0x1F2, 1); + outByte(0x1F3, offset); + outByte(0x1F4, offset >> 8); + outByte(0x1F5, offset >> 16); + outByte(0x1F6, (offset >> 24) | 0xE0); + outByte(0x1F7, 0x20); + + waitDisk(); + for (i = 0; i < SECTSIZE / 4; i ++) { + ((int *)dst)[i] = inLong(0x1F0); + } +} + +void initSeg() { + gdt[SEG_KCODE] = SEG(STA_X | STA_R, 0, 0xffffffff, DPL_KERN); + gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, DPL_KERN); + gdt[SEG_UCODE] = SEG(STA_X | STA_R, 0, 0xffffffff, DPL_USER); + gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER); + gdt[SEG_TSS] = SEG16(STS_T32A, &tss, sizeof(TSS)-1, DPL_KERN); + gdt[SEG_TSS].s = 0; + setGdt(gdt, sizeof(gdt)); + + /* + * 初始化TSS + */ + + tss.ss0 = KSEL(SEG_KDATA); + tss.esp0 = 0xf00000; //kernel stack + + asm volatile("ltr %%ax":: "a" (KSEL(SEG_TSS))); + + /*设置正确的段寄存器*/ + + lLdt(0); + +} + +void enterUserSpace(uint32_t entry) { + /* + * Before enter user space + * you should set the right segment registers here + * and use 'iret' to jump to ring3 + */ + uint32_t eflages = 0x00000002; + + asm volatile("movw %%ax, %%es":: "a"(USEL(SEG_UDATA))); //es + asm volatile("movw %%ax, %%ds":: "a"(USEL(SEG_UDATA))); //ds + + asm volatile("pushw %0":: "i"(USEL(SEG_UDATA))); //ss + asm volatile("pushl %0" :: "i"(128<<10)); //esp + + //iret will pop eip, cs, eflages + asm volatile("pushl %0" : : "m"(eflages)); //eflages + asm volatile("pushl %0":: "i"(USEL(SEG_UCODE))); //cs + asm volatile("pushl %0" : : "m"(entry)); //eip + + asm volatile("iret"); +} + + +void loadUMain(void) { + + /*加载用户程序至内存*/ + ELFHeader *elf; + ProgramHeader *ph = NULL; + + uint8_t buf[BUFSIZE]; + int i; + for(i=0; i <= NUM; i++) + readSect((void *)(buf+i*SECTSIZE), 201+i); + + elf = (void *)buf; + const uint32_t elf_magic = 0x464c457f; + uint32_t *p_magic = (void *)buf; + assert(*p_magic == elf_magic); + + for(i=0; i < elf->phnum; i++){ + ph = (ProgramHeader *)(buf + elf->phoff); + if(ph->type == PT_LOAD){ + memcpy((void *)ph->vaddr, buf+ph->off, ph->filesz); + memset((void *)(ph->vaddr+ph->filesz), 0, ph->memsz-ph->filesz); + } + } + assert(elf->entry == 0x200000); + enterUserSpace(elf->entry); +} + + + + diff --git a/lab2/kernel/kernel/serial.c b/lab2/kernel/kernel/serial.c new file mode 100644 index 0000000..0a02f75 --- /dev/null +++ b/lab2/kernel/kernel/serial.c @@ -0,0 +1,31 @@ +#include "x86.h" +#include "device.h" + +void initSerial(void) { + outByte(SERIAL_PORT + 1, 0x00); + outByte(SERIAL_PORT + 3, 0x80); + outByte(SERIAL_PORT + 0, 0x01); + outByte(SERIAL_PORT + 1, 0x00); + outByte(SERIAL_PORT + 3, 0x03); + outByte(SERIAL_PORT + 2, 0xC7); + outByte(SERIAL_PORT + 4, 0x0B); +} + +static inline int serialIdle(void) { + return (inByte(SERIAL_PORT + 5) & 0x20) != 0; +} + +void putChar(char ch) { + while (serialIdle() != TRUE); + outByte(SERIAL_PORT, ch); +} + +/* +int puts(char *buf, int len) +{ + int i; + for(i=0; i < len; i++) + putChar(buf[i]); + return i; +} +*/ diff --git a/lab2/kernel/lib/abort.c b/lab2/kernel/lib/abort.c new file mode 100644 index 0000000..4c848bc --- /dev/null +++ b/lab2/kernel/lib/abort.c @@ -0,0 +1,42 @@ +#include "common.h" +#include "x86.h" +#include "device.h" + +static char *i2A(int a) { + static char buf[30]; + char *p = buf + sizeof(buf) - 1; + do { + *--p = '0' + a % 10; + } while (a /= 10); + return p; +} + +static void append(char **p, const char *str) { + while (*str) { + *((*p) ++) = *str ++; + } +} + +/* 将文件名和assert fail的行号显示在屏幕上 */ +#define BLUE_SCREEN_TEXT "Assertion failed: " +static void displayMessage(const char *file, int line) { + static char buf[256] = BLUE_SCREEN_TEXT; + char *p = buf + sizeof(BLUE_SCREEN_TEXT) - 1; + + append(&p, file); + append(&p, ":"); + append(&p, i2A(line)); + append(&p, "\n"); + + for (p = buf; *p; p ++) { + putChar(*p); + } +} + +int abort(const char *fname, int line) { + disableInterrupt(); + displayMessage(fname, line); + while (TRUE) { + waitForInterrupt(); + } +} diff --git a/lab2/kernel/main.c b/lab2/kernel/main.c new file mode 100644 index 0000000..cb572c3 --- /dev/null +++ b/lab2/kernel/main.c @@ -0,0 +1,15 @@ +#include "common.h" +#include "x86.h" +#include "device.h" + +void kEntry(void) { + + initSerial();// initialize serial port + initIdt(); // initialize idt + initIntr(); // iniialize 8259a + initSeg(); // initialize gdt, tss + loadUMain(); // load user program, enter user space + + while(1); + assert(0); +} diff --git a/lab2/lab2.zip b/lab2/lab2.zip new file mode 100644 index 0000000000000000000000000000000000000000..e43de49f334b868ba1070d045da999241459b6a5 GIT binary patch literal 16608 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 QOu)ZdAhN{ag#7jY08}n&MF0Q* literal 0 HcmV?d00001 diff --git a/lab2/lib/lib.h b/lab2/lib/lib.h new file mode 100644 index 0000000..bef021e --- /dev/null +++ b/lab2/lib/lib.h @@ -0,0 +1,6 @@ +#ifndef __lib_h__ +#define __lib_h__ + +void printf(const char *format,...); + +#endif diff --git a/lab2/lib/syscall.c b/lab2/lib/syscall.c new file mode 100644 index 0000000..01e0492 --- /dev/null +++ b/lab2/lib/syscall.c @@ -0,0 +1,120 @@ +#include "lib.h" +#include "types.h" +//#include +/* + * io lib here + * 库函数写在这 + */ + +typedef char * va_list ; + +#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) -1) & ~(sizeof(int)-1)) +#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v)) +#define va_arg(ap, type) (*(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type))) +#define va_end(ap) (ap = (va_list)0) + +//int vsprintf(char *buf, const char *fmt, va_list args); + +int32_t syscall(int num, uint32_t a1,uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5) +{ + int32_t ret = 0; + + /* 内嵌汇编 保存 num, a1, a2, a3, a4, a5 至通用寄存器*/ + /* num--system call number + ** + */ + + asm volatile("movl %0, %%eax" :: "m"(num)); + asm volatile("movl %0, %%ecx" :: "m"(a1)); + asm volatile("movl %0, %%edx" :: "m"(a2)); + asm volatile("movl %0, %%ebx" :: "m"(a3)); + asm volatile("movl %0, %%esi" :: "m"(a4)); + asm volatile("movl %0, %%edi" :: "m"(a5)); + + asm volatile("int $0x80"); + + return ret; +} + +void write (void *buf, int len) +{ + int num = 4; + uint32_t fd = 1; + uint32_t ptr = (uint32_t)buf; + uint32_t size = (uint32_t)len; + + syscall(num, ptr, size, fd, 0, 0); +} + + +int itoa(int k, char *str, int hex) +{ + int i, j, n, base, sign; + char buf[32]; + if((k < 0) && hex == 10) { + sign = -1; + k = -k; + } + else sign = 1; + unsigned num = (unsigned)k; + i = 0; base = hex; + do{ + n = num % base; + if(n >= 0 && n <= 9) buf[i++] = n + '0'; + else buf[i++] = n + 'a'-10; + } while((num = num/base) > 0); + if(sign < 0) buf[i++] = '-'; + for(j=0; j < i; j++) + str[j] = buf[i-j-1]; + return i; +} + + + +int vsnprintf(char *buf, const char *format, va_list args) +{ + char *str; + char *arg; + + for(str=buf; *format; ++format){ + if(*format != '%'){ + *(str++) = *format; + continue; + } + format ++; + switch(*format){ + case 'x': + str += itoa(va_arg(args, int), str, 16); + break; + case 'c': + *(str++) = (unsigned char )va_arg(args, int); + break; + case 's': + arg = va_arg(args, char *); + for(; *arg; arg++) + *(str++) = *arg; + break; + case 'd': + str += itoa(va_arg(args, int), str, 10); + break; + default: *(str++) = *format; + } + + + } + va_end(args); + + return (str-buf); +} + + + +void printf(const char *format,...){ + static char buf[256]; + va_list args; + va_start(args, format); + int len = vsnprintf(buf, format, args); + write(buf, len); +} + diff --git a/lab2/lib/types.h b/lab2/lib/types.h new file mode 100644 index 0000000..deab367 --- /dev/null +++ b/lab2/lib/types.h @@ -0,0 +1,17 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned char boolean; + +typedef uint32_t size_t; +typedef int32_t pid_t; + + + +#endif diff --git a/lab2/utils/genBoot.pl b/lab2/utils/genBoot.pl new file mode 100644 index 0000000..5bc39bc --- /dev/null +++ b/lab2/utils/genBoot.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 1000); + +if($n > 510){ + print STDERR "ERROR: boot block too large: $n bytes (max 510)\n"; + exit 1; +} + +print STDERR "OK: boot block is $n bytes (max 510)\n"; + +$buf .= "\0" x (510-$n); +$buf .= "\x55\xAA"; + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/lab2/utils/genKernel.pl b/lab2/utils/genKernel.pl new file mode 100644 index 0000000..05ab188 --- /dev/null +++ b/lab2/utils/genKernel.pl @@ -0,0 +1,13 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 100000); + +print STDERR "OK: Kernel is $n bytes - Extended to 200 sectors\n"; + +$buf .= "\0" x (102400-$n); + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/lab3/Makefile b/lab3/Makefile new file mode 100644 index 0000000..1b2eaa5 --- /dev/null +++ b/lab3/Makefile @@ -0,0 +1,19 @@ +QEMU = qemu-system-i386 + +os.img: + @cd bootloader; make + @cd kernel; make + @cd app; make + cat bootloader/bootloader.bin kernel/kMain.elf app/uMain.elf > os.img + +play: os.img + $(QEMU) -serial stdio os.img + +debug: os.img + $(QEMU) -serial stdio -s -S os.img + +clean: + @cd bootloader; make clean + @cd kernel; make clean + @cd app; make clean + rm -f os.img diff --git a/lab3/app/Makefile b/lab3/app/Makefile new file mode 100644 index 0000000..259f8bf --- /dev/null +++ b/lab3/app/Makefile @@ -0,0 +1,17 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 -I../lib +LDFLAGS = -m elf_i386 + +UCFILES = $(shell find ./ -name "*.c") +LCFILES = $(shell find ../lib -name "*.c") +UOBJS = $(UCFILES:.c=.o) $(LCFILES:.c=.o) + +umain.bin: $(UOBJS) + $(LD) $(LDFLAGS) -e uEntry -Ttext 0x00200000 -o uMain.elf $(UOBJS) + +clean: + rm -rf $(UOBJS) uMain.elf diff --git a/lab3/app/main.c b/lab3/app/main.c new file mode 100644 index 0000000..e73bc04 --- /dev/null +++ b/lab3/app/main.c @@ -0,0 +1,30 @@ +#include "lib.h" + +int data = 0; + +int uEntry(void) { + int ret = fork(); + int i = 8; + + if (ret == 0) { + data = 2; + while( i != 0) { + i --; + printf("Child Process: Pong %d, %d;\n", data, i); + sleep(128); + } + exit(); + } + else if (ret != -1) { + data = 1; + while( i != 0) { + i --; + printf("Father Process: Ping %d, %d;\n", data, i); + sleep(128); + } + exit(); + } + while(1); + + return 0; +} diff --git a/lab3/bootloader/Makefile b/lab3/bootloader/Makefile new file mode 100644 index 0000000..76fa6e5 --- /dev/null +++ b/lab3/bootloader/Makefile @@ -0,0 +1,20 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 +ASFLAGS = -m32 +LDFLAGS = -m elf_i386 + +BSFILES = $(shell find ./ -name "*.S") +BCFILES = $(shell find ./ -name "*.c") +BOBJS = $(BSFILES:.S=.o) $(BCFILES:.c=.o) + +bootloader.bin: $(BOBJS) + $(LD) $(LDFLAGS) -e start -Ttext 0x7c00 -o bootloader.elf $(BOBJS) + objcopy -O binary bootloader.elf bootloader.bin + @../utils/genBoot.pl bootloader.bin + +clean: + rm -rf $(BOBJS) bootloader.elf bootloader.bin diff --git a/lab3/bootloader/boot.c b/lab3/bootloader/boot.c new file mode 100644 index 0000000..430e957 --- /dev/null +++ b/lab3/bootloader/boot.c @@ -0,0 +1,55 @@ +#include "boot.h" +#include + +#define SECTSIZE 512 +#define MAXNUM 200 +#define BUFSIZE (SECTSIZE*MAXNUM) + +#define NULL ((void *)0) + +void bootMain(void) { + /* 加载内核至内存,并跳转执行 */ + void (*kernel) (void); + + ELFHeader *elf; + ProgramHeader *ph; + + unsigned char buf[BUFSIZE]; + + int i=0; + for(i=0; i < MAXNUM; i++) + readSect((void *)(buf + i*SECTSIZE), i+1); + + elf = (void *)buf; + for(i=0; i < elf->phnum; i++){ + ph = (ProgramHeader *)(buf + elf->phoff + i * elf->phentsize); + int vaddr = ph->vaddr; + int filesz = ph->filesz; + memcpy((void *)vaddr, buf+ph->off, filesz); + memset((void *)(vaddr+filesz), 0, ph->memsz-filesz); + } + kernel = (void *)elf->entry; + kernel(); +} + +void waitDisk(void) { // waiting for disk + while((inByte(0x1F7) & 0xC0) != 0x40); +} + +void readSect(void *dst, int offset) { // reading a sector of disk + int i; + waitDisk(); + outByte(0x1F2, 1); + outByte(0x1F3, offset); + outByte(0x1F4, offset >> 8); + outByte(0x1F5, offset >> 16); + outByte(0x1F6, (offset >> 24) | 0xE0); + outByte(0x1F7, 0x20); + + waitDisk(); + for (i = 0; i < SECTSIZE / 4; i ++) { + ((int *)dst)[i] = inLong(0x1F0); + } +} + + diff --git a/lab3/bootloader/boot.h b/lab3/bootloader/boot.h new file mode 100644 index 0000000..b313576 --- /dev/null +++ b/lab3/bootloader/boot.h @@ -0,0 +1,59 @@ +#ifndef BOOT_H +#define BOOT_H + + +struct ELFHeader { + unsigned int magic; + unsigned char elf[12]; + unsigned short type; + unsigned short machine; + unsigned int version; + unsigned int entry; + unsigned int phoff; + unsigned int shoff; + unsigned int flags; + unsigned short ehsize; + unsigned short phentsize; + unsigned short phnum; + unsigned short shentsize; + unsigned short shnum; + unsigned short shstrndx; +}; + +/* ELF32 Program header */ +struct ProgramHeader { + unsigned int type; + unsigned int off; + unsigned int vaddr; + unsigned int paddr; + unsigned int filesz; + unsigned int memsz; + unsigned int flags; + unsigned int align; +}; + +typedef struct ELFHeader ELFHeader; +typedef struct ProgramHeader ProgramHeader; + +void waitDisk(void); + +void readSect(void *dst, int offset); + +/* I/O functions */ +static inline char inByte(short port) { + char data; + asm volatile("in %1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static inline int inLong(short port) { + int data; + asm volatile("in %1, %0" : "=a" (data) : "d" (port)); + return data; +} + +static inline void outByte(short port, char data) { + asm volatile("out %0,%1" : : "a" (data), "d" (port)); +} + +#endif diff --git a/lab3/bootloader/start.S b/lab3/bootloader/start.S new file mode 100644 index 0000000..7e340f2 --- /dev/null +++ b/lab3/bootloader/start.S @@ -0,0 +1,37 @@ +.code16 + +.global start +start: + cli #关闭中断 + inb $0x92, %al #启动A20总线 + orb $0x02, %al + outb %al, $0x92 + data32 addr32 lgdt gdtDesc #加载GDTR + movl %cr0, %eax #启动保护模式 + orb $0x01, %al + movl %eax, %cr0 + data32 ljmp $0x08, $start32 #长跳转切换至保护 + +.code32 +start32: + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movl $(128<<20), %esp + jmp bootMain + +.p2align 2 +gdt: # each table entry, at least 1 entry + .word 0,0 # empty entry + .byte 0,0,0,0 + + .word 0xffff,0 + .byte 0,0x9a,0xcf,0 + + .word 0xffff,0 + .byte 0,0x92,0xcf,0 + +gdtDesc: # 6 bytes in total + .word (gdtDesc - gdt -1) + .long gdt diff --git a/lab3/kernel/Makefile b/lab3/kernel/Makefile new file mode 100644 index 0000000..1dabd77 --- /dev/null +++ b/lab3/kernel/Makefile @@ -0,0 +1,20 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 -I./include +ASFLAGS = -m32 +LDFLAGS = -m elf_i386 + +KCFILES = $(shell find ./ -name "*.c") +KSFILES = $(shell find ./ -name "*.S") +KOBJS = $(KCFILES:.c=.o) $(KSFILES:.S=.o) + +kmain.bin: $(KOBJS) + $(LD) $(LDFLAGS) -e kEntry -Ttext 0x00100000 -o kMain.elf $(KOBJS) + @../utils/genKernel.pl kMain.elf + + +clean: + rm -rf $(KOBJS) kMain.elf kMain.bin diff --git a/lab3/kernel/include/common.h b/lab3/kernel/include/common.h new file mode 100644 index 0000000..f3f8b1d --- /dev/null +++ b/lab3/kernel/include/common.h @@ -0,0 +1,8 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "common/types.h" +#include "common/const.h" +#include "common/assert.h" + +#endif diff --git a/lab3/kernel/include/common/assert.h b/lab3/kernel/include/common/assert.h new file mode 100644 index 0000000..8c5e9bd --- /dev/null +++ b/lab3/kernel/include/common/assert.h @@ -0,0 +1,10 @@ +#ifndef __ASSERT_H__ +#define __ASSERT_H__ + +int abort(const char *, int); + +/* assert: 断言条件为真,若为假则蓝屏退出 */ +#define assert(cond) \ + ((cond) ? (0) : (abort(__FILE__, __LINE__))) + +#endif diff --git a/lab3/kernel/include/common/const.h b/lab3/kernel/include/common/const.h new file mode 100644 index 0000000..7a3f9eb --- /dev/null +++ b/lab3/kernel/include/common/const.h @@ -0,0 +1,9 @@ +#ifndef __CONST_H__ +#define __CONST_H__ + +#define TRUE 1 +#define FALSE 0 + +#define NULL ((void*)0) + +#endif diff --git a/lab3/kernel/include/common/types.h b/lab3/kernel/include/common/types.h new file mode 100644 index 0000000..ba71de2 --- /dev/null +++ b/lab3/kernel/include/common/types.h @@ -0,0 +1,15 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +/* 定义数据类型 */ +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned int size_t; + +#define PT_LOAD 1 + +#endif diff --git a/lab3/kernel/include/device.h b/lab3/kernel/include/device.h new file mode 100644 index 0000000..32dbdf2 --- /dev/null +++ b/lab3/kernel/include/device.h @@ -0,0 +1,6 @@ +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +#include "device/serial.h" + +#endif diff --git a/lab3/kernel/include/device/serial.h b/lab3/kernel/include/device/serial.h new file mode 100644 index 0000000..2c71d57 --- /dev/null +++ b/lab3/kernel/include/device/serial.h @@ -0,0 +1,8 @@ +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +void initSerial(void); +void putChar(char); +#define SERIAL_PORT 0x3F8 + +#endif diff --git a/lab3/kernel/include/x86.h b/lab3/kernel/include/x86.h new file mode 100644 index 0000000..91f2ce6 --- /dev/null +++ b/lab3/kernel/include/x86.h @@ -0,0 +1,13 @@ +#ifndef __X86_H__ +#define __X86_H__ + +#include "x86/cpu.h" +#include "x86/memory.h" +#include "x86/io.h" +#include "x86/irq.h" +#include "x86/debug.h" + +void initSeg(void); +uint32_t loadUMain(void); + +#endif diff --git a/lab3/kernel/include/x86/cpu.h b/lab3/kernel/include/x86/cpu.h new file mode 100644 index 0000000..744facd --- /dev/null +++ b/lab3/kernel/include/x86/cpu.h @@ -0,0 +1,32 @@ +#ifndef __X86_CPU_H__ +#define __X86_CPU_H__ + +#include "common.h" + +/* 将CPU置入休眠状态直到下次中断到来 */ +static inline void waitForInterrupt() { + asm volatile("hlt"); +} + +/* 修改IDTR */ +static inline void saveIdt(void *addr, uint32_t size) { + static volatile uint16_t data[3]; + data[0] = size - 1; + data[1] = (uint32_t)addr; + data[2] = ((uint32_t)addr) >> 16; + asm volatile("lidt (%0)" : : "r"(data)); +} + +/* 打开外部中断 */ +static inline void enableInterrupt(void) { + asm volatile("sti"); +} + +/* 关闭外部中断 */ +static inline void disableInterrupt(void) { + asm volatile("cli"); +} + +#define NR_IRQ 256 + +#endif diff --git a/lab3/kernel/include/x86/debug.h b/lab3/kernel/include/x86/debug.h new file mode 100644 index 0000000..124aa1d --- /dev/null +++ b/lab3/kernel/include/x86/debug.h @@ -0,0 +1,29 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#define DEBUG + +int putString(char *buf); +int putNum(int k, int hex); +void putTF(struct TrapFrame* tf); +void putPCB(struct ProcessTable *p); +void putList(); + +#ifdef DEBUG +#define LOG_STRING(str) putString(str) +#define LOG_NUM(k, hex) putNum(k, hex) +#define LOG_TF(tf) putTF(tf) +#define LOG_PCB(p) putPCB(p) +#define LOG_LIST() putList() + +#else +#define LOG_STRING(str) +#define LOG_NUM(k, hex) +#define LOG_TF(tf) +#define LOG_PCB(p) +#define LOG_LIST() + +#endif + + +#endif diff --git a/lab3/kernel/include/x86/io.h b/lab3/kernel/include/x86/io.h new file mode 100644 index 0000000..5fad01e --- /dev/null +++ b/lab3/kernel/include/x86/io.h @@ -0,0 +1,56 @@ +#ifndef __X86_IO_H__ +#define __X86_IO_H__ +/* ELF32二进制文件头 */ +struct ELFHeader { + unsigned int magic; + unsigned char elf[12]; + unsigned short type; + unsigned short machine; + unsigned int version; + unsigned int entry; + unsigned int phoff; + unsigned int shoff; + unsigned int flags; + unsigned short ehsize; + unsigned short phentsize; + unsigned short phnum; + unsigned short shentsize; + unsigned short shnum; + unsigned short shstrndx; +}; + +/* ELF32 Program header */ +struct ProgramHeader { + unsigned int type; + unsigned int off; + unsigned int vaddr; + unsigned int paddr; + unsigned int filesz; + unsigned int memsz; + unsigned int flags; + unsigned int align; +}; + +typedef struct ELFHeader ELFHeader; +typedef struct ProgramHeader ProgramHeader; + + +static inline int inLong(short port) { + int data; + asm volatile("in %1, %0" : "=a" (data) : "d" (port)); + return data; +} + +/* 读I/O端口 */ +static inline uint8_t inByte(uint16_t port) { + uint8_t data; + asm volatile("in %1, %0" : "=a"(data) : "d"(port)); + return data; +} + +/* 写I/O端口 */ +static inline void outByte(uint16_t port, int8_t data) { + asm volatile("out %%al, %%dx" : : "a"(data), "d"(port)); +} + +#endif diff --git a/lab3/kernel/include/x86/irq.h b/lab3/kernel/include/x86/irq.h new file mode 100644 index 0000000..4d2c161 --- /dev/null +++ b/lab3/kernel/include/x86/irq.h @@ -0,0 +1,8 @@ +#ifndef __IRQ_H__ +#define __IRQ_H__ + +/* 中断处理相关函数 */ +void initIdt(void); +void initIntr(void); + +#endif diff --git a/lab3/kernel/include/x86/memory.h b/lab3/kernel/include/x86/memory.h new file mode 100644 index 0000000..70e2bd1 --- /dev/null +++ b/lab3/kernel/include/x86/memory.h @@ -0,0 +1,151 @@ +#ifndef __X86_MEMORY_H__ +#define __X86_MEMORY_H__ + +#define DPL_KERN 0 +#define DPL_USER 3 + +// Application segment type bits +#define STA_X 0x8 // Executable segment +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) + +// System segment type bits +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate + +// GDT entries +#define NR_SEGMENTS 9 // GDT size +#define SEG_KCODE 1 // Kernel code +#define SEG_KDATA 2 // Kernel data/stack +#define SEG_UCODE 3 // User code +#define SEG_UDATA 4 // User data/stack +#define SEG_TSS 5 // Global unique task state segement + +// Selectors +#define KSEL(desc) (((desc) << 3) | DPL_KERN) +#define USEL(desc) (((desc) << 3) | DPL_USER) + +int current_index; +int current_base; + +struct GateDescriptor { + uint32_t offset_15_0 : 16; + uint32_t segment : 16; + uint32_t pad0 : 8; + uint32_t type : 4; + uint32_t system : 1; + uint32_t privilege_level : 2; + uint32_t present : 1; + uint32_t offset_31_16 : 16; +}; + +typedef struct GateDescriptor GateDescriptor; + +/* +struct TrapFrame { + uint32_t edi, esi, ebp, xxx, ebx, edx, ecx, eax; + int32_t irq; +};*/ + +/* +1. The number of bits in a bit field sets the limit to the range of values it can hold +2. Multiple adjacent bit fields are usually packed together (although this behavior is implementation-defined) + +Refer: en.cppreference.com/w/cpp/language/bit_field +*/ +struct SegDesc { + uint32_t lim_15_0 : 16; // Low bits of segment limit + uint32_t base_15_0 : 16; // Low bits of segment base address + uint32_t base_23_16 : 8; // Middle bits of segment base address + uint32_t type : 4; // Segment type (see STS_ constants) + uint32_t s : 1; // 0 = system, 1 = application + uint32_t dpl : 2; // Descriptor Privilege Level + uint32_t p : 1; // Present + uint32_t lim_19_16 : 4; // High bits of segment limit + uint32_t avl : 1; // Unused (available for software use) + uint32_t rsv1 : 1; // Reserved + uint32_t db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + uint32_t g : 1; // Granularity: limit scaled by 4K when set + uint32_t base_31_24 : 8; // High bits of segment base address +}; +typedef struct SegDesc SegDesc; + +#define SEG(type, base, lim, dpl) (SegDesc) \ +{ ((lim) >> 12) & 0xffff, (uint32_t)(base) & 0xffff, \ + ((uint32_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uint32_t)(lim) >> 28, 0, 0, 1, 1, (uint32_t)(base) >> 24 } + +#define SEG16(type, base, lim, dpl) (SegDesc) \ +{ (lim) & 0xffff, (uint32_t)(base) & 0xffff, \ + ((uint32_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \ + (uint32_t)(lim) >> 16, 0, 0, 1, 0, (uint32_t)(base) >> 24 } + +// Task state segment format +struct TSS { + uint32_t link; // old ts selector + uint32_t esp0; // Ring 0 Stack pointer and segment selector + uint32_t ss0; // after an increase in privilege level + union{ + struct{ + char dontcare[88]; + }; + struct{ + uint32_t esp1,ss1,esp2,ss2; + uint32_t cr3, eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; + uint32_t es, cs, ss, ds, fs, gs, ldt; + }; + }; +}; +typedef struct TSS TSS; + +#define MAX_STACK_SIZE 0x2000 +#define MAX_PCB_NUM 32 +#define TASK_FREE 0 +#define TASK_RUNNING 1 +#define TASK_RUNNABLE 2 +#define TASK_BLOCKED 3 +#define TASK_DEAD 4 + + + +struct TrapFrame { + uint32_t gs, fs, es, ds; + uint32_t edi, esi, ebp, xxx, ebx, edx, ecx, eax; + uint32_t irq; + uint32_t error; + uint32_t eip, cs, eflags, esp, ss; +}; + +struct ProcessTable{ + struct TrapFrame *tf; + int state; + int timeCount; + int sleepTime; + uint32_t pid; + struct ProcessTable *link; + uint32_t stack[MAX_STACK_SIZE]; +}; +struct ProcessTable pcb[MAX_PCB_NUM]; +struct ProcessTable *current; +struct ProcessTable *run_list;//runnable list +int next_pcb; +int nr_process; +int need_resched; + + + +static inline void setGdt(SegDesc *gdt, uint32_t size) { + volatile static uint16_t data[3]; + data[0] = size - 1; + data[1] = (uint32_t)gdt; + data[2] = (uint32_t)gdt >> 16; + asm volatile("lgdt (%0)" : : "r"(data)); +} + +static inline void lLdt(uint16_t sel) +{ + asm volatile("lldt %0" :: "r"(sel)); +} + +#endif diff --git a/lab3/kernel/kernel/debug.c b/lab3/kernel/kernel/debug.c new file mode 100644 index 0000000..57769d5 --- /dev/null +++ b/lab3/kernel/kernel/debug.c @@ -0,0 +1,78 @@ +#include "x86.h" + + +void putChar(char ch); + + +int itoa(int k, char *str, int hex) +{ + int i, j, n, base, sign; + char buf[32]; + if((k < 0) && hex == 10) { + sign = -1; + k = -k; + } + else sign = 1; + unsigned num = (unsigned)k; + i = 0; base = hex; + do{ + n = num % base; + if(n >= 0 && n <= 9) buf[i++] = n + '0'; + else buf[i++] = n + 'a'-10; + } while((num = num/base) > 0); + if(sign < 0) buf[i++] = '-'; + for(j=0; j < i; j++) + str[j] = buf[i-j-1]; + return i; +} + +int putString(char *buf) +{ + char *p = buf; + while(*p != '\0'){ + putChar(*p); + p++; + } + return (int)(p-buf); +} + +int putNum(int k, int hex) +{ + int i; + char buf[32]; + int len = itoa(k, buf, hex); + for(i=0; i < len; i++){ + putChar(buf[i]); + } + return len; +} + +void putTF(struct TrapFrame* tf) +{ + putString("%ds=0x"); putNum(tf->ds, 16); putString(" "); + putString("%cs=0x"); putNum(tf->cs, 16); putString(" "); + putString("%ss=0x"); putNum(tf->ss, 16); putString("\n"); + putString("%eip=0x"); putNum(tf->eip, 16); putString(" "); + putString("%esp=0x"); putNum(tf->esp, 16); putString(" "); + putString("irq=0x"); putNum(tf->irq, 16); putString("\n"); +} + +void putPCB(struct ProcessTable *p) +{ + putTF(p->tf); + putString("pid=0x"); putNum(p->pid, 16); putString(" "); + putString("state=0x"); putNum(p->state, 16); putString(" "); + putString("timeCount=0x"); putNum(p->timeCount, 16); putString(" "); + putString("sleepTime=0x"); putNum(p->sleepTime, 16); putString("\n"); +} + +void putList() +{ + int i = 0; + struct ProcessTable *p = run_list; + while(p != NULL){ + putString("i="); putNum(i, 10); putString(", "); + putString("pid="); putNum(p->pid, 10); putString("\n"); + p = p->link; i++; + } +} diff --git a/lab3/kernel/kernel/doIrq.S b/lab3/kernel/kernel/doIrq.S new file mode 100644 index 0000000..70cf2cf --- /dev/null +++ b/lab3/kernel/kernel/doIrq.S @@ -0,0 +1,50 @@ +.code32 + +.global irqEmpty +irqEmpty: + pushl $0 // push dummy error code + pushl $-1 // push interrupt vector into kernel + jmp asmDoIrq + +.global irqGProtectFault +irqGProtectFault: + pushl $0xd + jmp asmDoIrq + +.global irqSyscall +irqSyscall: + pushl $0 // push dummy error code + pushl $0x80 // push interrupt vector into kernel stack + jmp asmDoIrq + +.global irqTime +irqTime: + pushl $0 + pushl $0x20 + jmp asmDoIrq + +.extern current + +.global asmDoIrq +asmDoIrq: + cli + pushal // push process state into kernel stack + pushl %ds + pushl %es + pushl %fs + pushl %gs + pushl %esp + movl $0x10, %eax + movl %eax, %ds + movl %eax, %es + call irqHandle + movl (current), %eax + movl (%eax), %esp + popl %gs + popl %fs + popl %es + popl %ds + popal + addl $4, %esp //interrupt vector is on top of kernel stack + addl $4, %esp //error code is on top of kernel stack + iret diff --git a/lab3/kernel/kernel/i8259.c b/lab3/kernel/kernel/i8259.c new file mode 100644 index 0000000..7e50866 --- /dev/null +++ b/lab3/kernel/kernel/i8259.c @@ -0,0 +1,26 @@ +#include "x86.h" + +#define PORT_PIC_MASTER 0x20 +#define PORT_PIC_SLAVE 0xA0 +#define IRQ_SLAVE 2 + +/* 初始化8259中断控制器: + * 硬件中断IRQ从32号开始,自动发送EOI */ +void +initIntr(void) { + outByte(PORT_PIC_MASTER + 1, 0xFF); + outByte(PORT_PIC_SLAVE + 1 , 0xFF); + outByte(PORT_PIC_MASTER, 0x11); // Initialization command + outByte(PORT_PIC_MASTER + 1, 32); // Interrupt Vector Offset 0x20 + outByte(PORT_PIC_MASTER + 1, 1 << 2); // Tell Master PIC that there is a slave + outByte(PORT_PIC_MASTER + 1, 0x3); // Auto EOI in 8086/88 mode + outByte(PORT_PIC_SLAVE, 0x11); // Initialization command + outByte(PORT_PIC_SLAVE + 1, 32 + 8); // Interrupt Vector Offset 0x28 + outByte(PORT_PIC_SLAVE + 1, 2); // Tell Slave PIC its cascade identity + outByte(PORT_PIC_SLAVE + 1, 0x3); // Auto EOI in 8086/88 mode + + outByte(PORT_PIC_MASTER, 0x68); + outByte(PORT_PIC_MASTER, 0x0A); + outByte(PORT_PIC_SLAVE, 0x68); + outByte(PORT_PIC_SLAVE, 0x0A); +} diff --git a/lab3/kernel/kernel/idle.c b/lab3/kernel/kernel/idle.c new file mode 100644 index 0000000..045b146 --- /dev/null +++ b/lab3/kernel/kernel/idle.c @@ -0,0 +1,95 @@ +#include "x86.h" +//#include + +struct ProcessTable pcb[MAX_PCB_NUM]; +struct ProcessTable idle_pcb; +struct ProcessTable *current;//the task is running +struct ProcessTable *run_list;//runnable list +int nr_process;//number of process +int need_resched;//if need reschedule +struct TSS tss; + +int puts(char *buf, int len); + +void add_to_queue(struct ProcessTable *m) +{ + struct ProcessTable *pre = run_list; + if(pre == NULL){ + m->link = NULL; + run_list = m; + } + else{ + for(; !pre->link; pre=pre->link); + pre->link = m; + m->link = NULL; + } +} + +void del_to_queue(struct ProcessTable *m) +{ + struct ProcessTable *pre = run_list; + if(!run_list) return; + if(run_list == m){ + run_list = run_list->link; + pre->link = NULL; + } + else{ + for(; pre->link && pre->link != m; pre=pre->link); + if(pre->link == m){ + struct ProcessTable *tmp = pre->link; + pre->link = tmp->link; + tmp->link = NULL; + } + } +} + +void idle() +{ + if(nr_process != 0) + enableInterrupt(); + waitForInterrupt(); +} + +void initPCB() +{ + int i; + for(i=0; i < MAX_PCB_NUM; i++){ + pcb[i].state = TASK_FREE; + pcb[i].timeCount = 0; + pcb[i].sleepTime = 0; + pcb[i].pid = -1; + } + current = NULL; + run_list = NULL; + nr_process = 0; + next_pcb = 0; + need_resched = 0;//if need reschedule +} + +struct ProcessTable* initUserProcess(uint32_t entry) +{ + int i = next_pcb++; + pcb[i].state = TASK_RUNNABLE; + pcb[i].timeCount = 20; + pcb[i].sleepTime = 0; + pcb[i].pid = 1; + + pcb[i].tf = (struct TrapFrame *)(pcb[0].stack + MAX_STACK_SIZE) - 1; + + pcb[i].tf->eip = entry; + pcb[i].tf->cs = USEL(SEG_UCODE); + pcb[i].tf->eflags = 0x202; + pcb[i].tf->esp = 0x400000; + pcb[i].tf->ss = USEL(SEG_UDATA); + pcb[i].tf->ds = USEL(SEG_UDATA); + pcb[i].tf->es = USEL(SEG_UDATA); + add_to_queue(&pcb[i]); + need_resched = 1; + nr_process ++; + + return &pcb[0]; +} + + + + diff --git a/lab3/kernel/kernel/idt.c b/lab3/kernel/kernel/idt.c new file mode 100644 index 0000000..3b07914 --- /dev/null +++ b/lab3/kernel/kernel/idt.c @@ -0,0 +1,58 @@ +#include "x86.h" +#include "device.h" + +#define INTERRUPT_GATE_32 0xE +#define TRAP_GATE_32 0xF + +/* IDT表的内容 */ +struct GateDescriptor idt[NR_IRQ]; // NR_IRQ=256, defined in x86/cpu.h + +/* 初始化一个中断门(interrupt gate) */ +static void setIntr(struct GateDescriptor *ptr, uint32_t selector, uint32_t offset, uint32_t dpl) { + ptr->offset_15_0 = offset & 0xFFFF; + ptr->segment = selector << 3; + ptr->pad0 = 0; + ptr->type = INTERRUPT_GATE_32; + ptr->system = FALSE; + ptr->privilege_level = dpl; + ptr->present = TRUE; + ptr->offset_31_16 = (offset >> 16) & 0xFFFF; +} + +/* 初始化一个陷阱门(trap gate) */ +static void setTrap(struct GateDescriptor *ptr, uint32_t selector, uint32_t offset, uint32_t dpl) { + ptr->offset_15_0 = offset & 0xFFFF; + ptr->segment = selector << 3; + ptr->pad0 = 0; + ptr->type = TRAP_GATE_32; + ptr->system = FALSE; + ptr->privilege_level = dpl; + ptr->present = TRUE; + ptr->offset_31_16 = (offset >> 16) & 0xFFFF; +} + +/* 声明函数,这些函数在汇编代码里定义 */ +void irqEmpty(); +void irqGProtectFault(); +void irqSyscall(); +void irqTime(); + +void initIdt() { + int i; + /* 为了防止系统异常终止,所有irq都有处理函数(irqEmpty)。 */ + for (i = 0; i < NR_IRQ; i ++) { + setTrap(idt + i, SEG_KCODE, (uint32_t)irqEmpty, DPL_KERN); + } + /* + * init your idt here + * 初始化 IDT 表, 为中断设置中断处理函数 + */ + + setTrap(idt + 0xd, SEG_KCODE, (uint32_t)irqGProtectFault, DPL_KERN); + + setIntr(idt + 0x80, SEG_KCODE, (uint32_t)irqSyscall, DPL_USER); // for int 0x80, interrupt vector is 0x80, Interruption is disabled + setIntr(idt + 0x20, SEG_KCODE, (uint32_t)irqTime, DPL_USER); // for int 0x80, interrupt vector is 0x80, Interruption is disabled + + /* 写入IDT */ + saveIdt(idt, sizeof(idt)); +} diff --git a/lab3/kernel/kernel/irqHandle.c b/lab3/kernel/kernel/irqHandle.c new file mode 100644 index 0000000..f083a79 --- /dev/null +++ b/lab3/kernel/kernel/irqHandle.c @@ -0,0 +1,194 @@ +#include "x86.h" +#include "device.h" +#include + +#define SYS_WRITE 4 +#define SYS_EXIT 1 +#define SYS_FORK 2 +#define SYS_SLEEP 3 + +#define G_PORT (0xb800) + +SegDesc gdt[NR_SEGMENTS]; +TSS tss; + +void syscallHandle(struct TrapFrame *tf); + +void GProtectFaultHandle(struct TrapFrame *tf); + +void TimeBreakHandle(struct TrapFrame *tf); + +int puts(char *, int); + +void add_to_queue(struct ProcessTable *m); +void del_to_queue(struct ProcessTable *m); +void schedule(); +void idle(); + +void irqHandle(struct TrapFrame *tf) { + /* + * 中断处理程序 + */ + /* Reassign segment register */ + + LOG_LIST(); + + if(current != NULL){ + memcpy(current->tf, tf, sizeof(struct TrapFrame)); + LOG_PCB(current); + } + + switch(tf->irq) { + case -1: + break; + case 0xd: + GProtectFaultHandle(tf); + break; + case 0x20: + TimeBreakHandle(tf); + break; + case 0x80: + syscallHandle(tf); + break; + default: + assert(0); + } + if(need_resched == 1) + schedule(); + + if(current == NULL) idle(); + + LOG_STRING("-------------------\n"); +} + +static void sys_write(struct TrapFrame *tf) +{ + int fd = (tf->ebx); + uint32_t segBase = (uint32_t )(gdt[tf->ds >> 3].base_15_0 + (gdt[tf->ds>>3].base_23_16<<16) + (gdt[tf->ds >> 3].base_31_24 << 24)); + assert(tf->edx != 0); + char *buf = (char *)(tf->ecx + segBase); + int len = tf->edx; + if(fd == 1) + puts(buf, len); + else + assert(0); +} + +static void sys_exit(struct TrapFrame *tf) +{ + current->state = TASK_FREE; + need_resched = 1; + + nr_process--; + return; +} + +static void sys_fork(struct TrapFrame *tf) +{ + uint32_t *father_start = (uint32_t *)(gdt[tf->ds >> 3].base_15_0 + (gdt[tf->ds>>3].base_23_16<<16) + (gdt[tf->ds >> 3].base_31_24 << 24)); + uint32_t newSegBase = current_base; + current_base += 0x400000; + uint32_t *cd_start = (uint32_t *)newSegBase; + memcpy(cd_start, father_start, 0x400000); + struct ProcessTable *newpcb = &pcb[next_pcb++]; + memcpy(newpcb->stack, current->stack, MAX_STACK_SIZE*sizeof(uint32_t)); + newpcb->tf = (struct TrapFrame *)(newpcb->stack + MAX_STACK_SIZE) - 1; + memcpy(newpcb->tf, tf, sizeof(struct TrapFrame)); + newpcb->tf->eax = 0; //child process return 0 + current->tf->eax = 2; //father process return pid of child + //creat new gdt + int newSegCodeIndex = current_index++; + int newSegDataIndex = current_index++; + gdt[newSegCodeIndex] = SEG(STA_X | STA_R, newSegBase, 0x400000, DPL_USER); + gdt[newSegDataIndex] = SEG(STA_W, newSegBase, 0x400000, DPL_USER); + newpcb->tf->es = USEL(newSegDataIndex); + newpcb->tf->ss = USEL(newSegDataIndex); + newpcb->tf->ds = USEL(newSegDataIndex); + newpcb->tf->gs = USEL(newSegDataIndex); + newpcb->tf->cs = USEL(newSegCodeIndex); + newpcb->state = TASK_RUNNABLE; + newpcb->timeCount = 10; + newpcb->pid = 2; + add_to_queue(newpcb); + nr_process++; + + return; +} + +static void sys_sleep(struct TrapFrame *tf) +{ + current->state = TASK_BLOCKED; + current->sleepTime = tf->ecx; + need_resched = 1; + + return; +} + +void syscallHandle(struct TrapFrame *tf) { + /* 实现系统调用*/ + + LOG_STRING("syscall: nr=0x"); + LOG_NUM(tf->eax, 16); + LOG_STRING("\n"); + + switch(tf->eax){ + case SYS_WRITE: sys_write(tf); break; + case SYS_FORK: sys_fork(tf); break; + case SYS_EXIT: sys_exit(tf); break; + case SYS_SLEEP: sys_sleep(tf); break; + default: assert(0); + } +} + +void GProtectFaultHandle(struct TrapFrame *tf){ + assert(0); + return; +} + + +void TimeBreakHandle(struct TrapFrame *tf) +{ + int i; + for(i=0; i < MAX_PCB_NUM; i++){ + if(pcb[i].state == TASK_RUNNING){ + pcb[i].timeCount --; + if(pcb[i].timeCount == 0){ + pcb[i].state = TASK_RUNNABLE; + add_to_queue(&pcb[i]); + need_resched = 1; + } + } + else if(pcb[i].state == TASK_BLOCKED){ + pcb[i].sleepTime --; + if(pcb[i].sleepTime == 0){ + pcb[i].state = TASK_RUNNABLE; + pcb[i].timeCount = 10; + add_to_queue(&pcb[i]); + //need_resched = 1; + } + + } + } + + return ; +} + +int puts(char *buf, int len) +{ + char *p1 = (char *)0xb8000; + char *p2 = buf; + static int off = 640; + int i; + for(i=0; i < len; i++){ + if(*p2 == '\n'){ + off = (off/160+1)*160; + p2 ++; + } + else{ + *(p1+off) = *(p2++); + *(p1+off+1) = 0x0c; + off += 2; + } + } + return p2-buf; +} diff --git a/lab3/kernel/kernel/kvm.c b/lab3/kernel/kernel/kvm.c new file mode 100644 index 0000000..9bfc593 --- /dev/null +++ b/lab3/kernel/kernel/kvm.c @@ -0,0 +1,117 @@ +#include "x86.h" +#include "device.h" +#include + +SegDesc gdt[NR_SEGMENTS]; +TSS tss; + +#define SECTSIZE 512 +#define NUM 200 +#define BUFSIZE (SECTSIZE*NUM) + +void waitDisk(void) { + while((inByte(0x1F7) & 0xC0) != 0x40); +} + +void readSect(void *dst, int offset) { + int i; + waitDisk(); + + outByte(0x1F2, 1); + outByte(0x1F3, offset); + outByte(0x1F4, offset >> 8); + outByte(0x1F5, offset >> 16); + outByte(0x1F6, (offset >> 24) | 0xE0); + outByte(0x1F7, 0x20); + + waitDisk(); + for (i = 0; i < SECTSIZE / 4; i ++) { + ((int *)dst)[i] = inLong(0x1F0); + } +} + +void initSeg() { + gdt[SEG_KCODE] = SEG(STA_X | STA_R, 0, 0xffffffff, DPL_KERN); + gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, DPL_KERN); + gdt[SEG_UCODE] = SEG(STA_X | STA_R, 0x400000, 0xffffffff, DPL_USER); + gdt[SEG_UDATA] = SEG(STA_W, 0x400000, 0xffffffff, DPL_USER); + gdt[SEG_TSS] = SEG16(STS_T32A, &tss, sizeof(TSS)-1, DPL_KERN); + gdt[SEG_TSS].s = 0; + + setGdt(gdt, sizeof(gdt)); + + /* + * 初始化TSS + */ + current_index = SEG_TSS + 1; + current_base = 0x800000; + + tss.ss0 = KSEL(SEG_KDATA); + tss.esp0 = 0x400000; + + asm volatile("ltr %%ax":: "a" (KSEL(SEG_TSS))); + + /*设置正确的段寄存器*/ + asm volatile("movw %%ax, %%es":: "a"(KSEL(SEG_KDATA))); //es + asm volatile("movw %%ax, %%ds":: "a"(KSEL(SEG_KDATA))); //ds + asm volatile("movw %%ax, %%ss":: "a"(KSEL(SEG_KDATA))); //ss + + lLdt(0); + +} + +void enterUserSpace(uint32_t entry) { + /* + * Before enter user space + * you should set the right segment registers here + * and use 'iret' to jump to ring3 + */ + uint32_t eflages = 0x00000002; + + asm volatile("movw %%ax, %%es":: "a"(USEL(SEG_UDATA))); //es + asm volatile("movw %%ax, %%ds":: "a"(USEL(SEG_UDATA))); //ds + + asm volatile("pushw %0":: "i"(USEL(SEG_UDATA))); //ss + asm volatile("pushl %0" :: "i"(128<<10)); //esp + + //iret will pop eip, cs, eflages + asm volatile("pushl %0" : : "m"(eflages)); //eflages + asm volatile("pushl %0":: "i"(USEL(SEG_UCODE))); //cs + asm volatile("pushl %0" : : "m"(entry)); //eip + + asm volatile("iret"); +} + + +uint32_t loadUMain() { + + /*加载用户程序至内存*/ + ELFHeader *elf; + ProgramHeader *ph = NULL; + char *p; + + uint8_t buf[BUFSIZE]; + int i; + for(i=0; i < NUM; i++) + readSect((void *)(buf+i*SECTSIZE), 201+i); + + elf = (void *)buf; + const uint32_t elf_magic = 0x464c457f; + uint32_t *p_magic = (void *)buf; + assert(*p_magic == elf_magic); + + for(i=0; i < elf->phnum; i++){ + ph = (ProgramHeader *)(buf + elf->phoff + elf->phentsize*i); + if(ph->type == PT_LOAD){ + p = (char *)ph->vaddr+0x400000; + memcpy(p, buf+ph->off, ph->filesz); + memset((void *)(p+ph->filesz), 0, ph->memsz-ph->filesz); + } + } + assert(elf->entry == 0x200000); + return elf->entry; +} + + + + diff --git a/lab3/kernel/kernel/schedule.c b/lab3/kernel/kernel/schedule.c new file mode 100644 index 0000000..251b532 --- /dev/null +++ b/lab3/kernel/kernel/schedule.c @@ -0,0 +1,33 @@ +#include "x86.h" + +struct TSS tss; + +void add_to_queue(struct ProcessTable *m); +void del_to_queue(struct ProcessTable *m); + + +void schedule() +{ + if(need_resched == 0) return; + + struct ProcessTable *next; + next = NULL; + if(current != NULL && current->state == TASK_RUNNING) {} + else if((current == NULL || current->state == TASK_BLOCKED) && run_list){ + next = run_list; + del_to_queue(next); + } + else{ + next = NULL; + } + if(next != NULL){//swithch to next + tss.esp0 = (uint32_t)(next->stack+MAX_STACK_SIZE - sizeof(struct TrapFrame)); + + current = next; + current->state = TASK_RUNNING; + if(current->timeCount <= 0) current->timeCount = 10; + } + else current = NULL; + +} + diff --git a/lab3/kernel/kernel/serial.c b/lab3/kernel/kernel/serial.c new file mode 100644 index 0000000..39b17fa --- /dev/null +++ b/lab3/kernel/kernel/serial.c @@ -0,0 +1,24 @@ +#include "x86.h" +#include "device.h" + + + +void initSerial(void) { + outByte(SERIAL_PORT + 1, 0x00); + outByte(SERIAL_PORT + 3, 0x80); + outByte(SERIAL_PORT + 0, 0x01); + outByte(SERIAL_PORT + 1, 0x00); + outByte(SERIAL_PORT + 3, 0x03); + outByte(SERIAL_PORT + 2, 0xC7); + outByte(SERIAL_PORT + 4, 0x0B); +} + +static inline int serialIdle(void) { + return (inByte(SERIAL_PORT + 5) & 0x20) != 0; +} + +void putChar(char ch) { + while (serialIdle() != TRUE); + outByte(SERIAL_PORT, ch); +} + diff --git a/lab3/kernel/kernel/timer.c b/lab3/kernel/kernel/timer.c new file mode 100644 index 0000000..2ee4e71 --- /dev/null +++ b/lab3/kernel/kernel/timer.c @@ -0,0 +1,12 @@ +#include "x86.h" + +#define TIMER_PORT 0x40 +#define FREQ_8253 1193182 +#define HZ 100 + +void initTimer() { + int counter = FREQ_8253 / HZ; + outByte(TIMER_PORT + 3, 0x34); + outByte(TIMER_PORT + 0, counter % 256); + outByte(TIMER_PORT + 0, counter / 256); +} diff --git a/lab3/kernel/lib/abort.c b/lab3/kernel/lib/abort.c new file mode 100644 index 0000000..4c848bc --- /dev/null +++ b/lab3/kernel/lib/abort.c @@ -0,0 +1,42 @@ +#include "common.h" +#include "x86.h" +#include "device.h" + +static char *i2A(int a) { + static char buf[30]; + char *p = buf + sizeof(buf) - 1; + do { + *--p = '0' + a % 10; + } while (a /= 10); + return p; +} + +static void append(char **p, const char *str) { + while (*str) { + *((*p) ++) = *str ++; + } +} + +/* 将文件名和assert fail的行号显示在屏幕上 */ +#define BLUE_SCREEN_TEXT "Assertion failed: " +static void displayMessage(const char *file, int line) { + static char buf[256] = BLUE_SCREEN_TEXT; + char *p = buf + sizeof(BLUE_SCREEN_TEXT) - 1; + + append(&p, file); + append(&p, ":"); + append(&p, i2A(line)); + append(&p, "\n"); + + for (p = buf; *p; p ++) { + putChar(*p); + } +} + +int abort(const char *fname, int line) { + disableInterrupt(); + displayMessage(fname, line); + while (TRUE) { + waitForInterrupt(); + } +} diff --git a/lab3/kernel/main.c b/lab3/kernel/main.c new file mode 100644 index 0000000..3adee1a --- /dev/null +++ b/lab3/kernel/main.c @@ -0,0 +1,30 @@ +#include "common.h" +#include "x86.h" +#include "device.h" + +void initTimer(); +void initPCB(); +struct ProcessTable* initUserProcess(uint32_t entry); +void EnterUserSpace(struct ProcessTable *p); + +void kEntry(void) { + + initSerial();// initialize serial port + initIdt(); // initialize idt + initIntr(); // iniialize 8259a + initSeg(); // initialize gdt, tss + initTimer(); + uint32_t entry = loadUMain(); // load user program, enter user space + initPCB(); + //struct ProcessTable *p = initUserProcess(entry); + initUserProcess(entry); + enableInterrupt(); + //EnterUserSpace(p); + + while(1){ + waitForInterrupt(); + } + + while(1); + assert(0); +} diff --git a/lab3/lib/lib.h b/lab3/lib/lib.h new file mode 100644 index 0000000..72a5314 --- /dev/null +++ b/lab3/lib/lib.h @@ -0,0 +1,11 @@ +#ifndef __lib_h__ +#define __lib_h__ + +#include "types.h" + +void printf(const char *format,...); +int fork(); +int sleep(uint32_t time); +int exit(); + +#endif diff --git a/lab3/lib/syscall.c b/lab3/lib/syscall.c new file mode 100644 index 0000000..913bbce --- /dev/null +++ b/lab3/lib/syscall.c @@ -0,0 +1,152 @@ +#include "lib.h" +#include "types.h" +//#include +/* + * io lib here + * 库函数写在这 + */ + +typedef char * va_list ; + +#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) -1) & ~(sizeof(int)-1)) +#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v)) +#define va_arg(ap, type) (*(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type))) +#define va_end(ap) (ap = (va_list)0) + +//int vsprintf(char *buf, const char *fmt, va_list args); + +int32_t syscall(int num, uint32_t a1,uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5) +{ + int32_t ret = 0; + + /* 内嵌汇编 保存 num, a1, a2, a3, a4, a5 至通用寄存器*/ + /* num--system call number + ** + */ + + asm volatile("pushl %ebx;\ + pushl %esi;\ + pushl %edi"); + asm volatile("movl %0, %%eax" :: "m"(num)); + asm volatile("movl %0, %%ecx" :: "m"(a1)); + asm volatile("movl %0, %%edx" :: "m"(a2)); + asm volatile("movl %0, %%ebx" :: "m"(a3)); + asm volatile("movl %0, %%esi" :: "m"(a4)); + asm volatile("movl %0, %%edi" :: "m"(a5)); + + asm volatile("int $0x80"); + + asm volatile("movl %%eax, %0" :"=m"(ret) :); + asm volatile("popl %edi;\ + popl %esi;\ + popl %ebx"); + + return ret; +} + +void write (void *buf, int len) +{ + int num = 4; + uint32_t fd = 1; + uint32_t ptr = (uint32_t)buf; + uint32_t size = (uint32_t)len; + + syscall(num, ptr, size, fd, 0, 0); +} + + +int itoa(int k, char *str, int hex) +{ + int i, j, n, base, sign; + char buf[32]; + if((k < 0) && hex == 10) { + sign = -1; + k = -k; + } + else sign = 1; + unsigned num = (unsigned)k; + i = 0; base = hex; + do{ + n = num % base; + if(n >= 0 && n <= 9) buf[i++] = n + '0'; + else buf[i++] = n + 'a'-10; + } while((num = num/base) > 0); + if(sign < 0) buf[i++] = '-'; + for(j=0; j < i; j++) + str[j] = buf[i-j-1]; + return i; +} + + + +int vsnprintf(char *buf, const char *format, va_list args) +{ + char *str; + char *arg; + + for(str=buf; *format; ++format){ + if(*format != '%'){ + *(str++) = *format; + continue; + } + format ++; + switch(*format){ + case 'x': + str += itoa(va_arg(args, int), str, 16); + break; + case 'c': + *(str++) = (unsigned char )va_arg(args, int); + break; + case 's': + arg = va_arg(args, char *); + for(; *arg; arg++) + *(str++) = *arg; + break; + case 'd': + str += itoa(va_arg(args, int), str, 10); + break; + default: *(str++) = *format; + } + + + } + va_end(args); + + return (str-buf); +} + + + +void printf(const char *format,...){ + static char buf[256]; + va_list args; + va_start(args, format); + int len = vsnprintf(buf, format, args); + write(buf, len); +} + + + +int fork() +{ + int num = 2; + int ret = syscall(num, 0, 0, 0, 0, 0); + return ret; +} + + +int sleep(uint32_t time) +{ + int num = 3; + int ret = syscall(num, time, 0, 0, 0, 0); + return ret; +} + +int exit() +{ + int num = 1; + int ret = syscall(num, 0, 0, 0, 0, 0); + return ret; +} + diff --git a/lab3/lib/types.h b/lab3/lib/types.h new file mode 100644 index 0000000..deab367 --- /dev/null +++ b/lab3/lib/types.h @@ -0,0 +1,17 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned char boolean; + +typedef uint32_t size_t; +typedef int32_t pid_t; + + + +#endif diff --git a/lab3/utils/genBoot.pl b/lab3/utils/genBoot.pl new file mode 100644 index 0000000..5bc39bc --- /dev/null +++ b/lab3/utils/genBoot.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 1000); + +if($n > 510){ + print STDERR "ERROR: boot block too large: $n bytes (max 510)\n"; + exit 1; +} + +print STDERR "OK: boot block is $n bytes (max 510)\n"; + +$buf .= "\0" x (510-$n); +$buf .= "\x55\xAA"; + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/lab3/utils/genKernel.pl b/lab3/utils/genKernel.pl new file mode 100644 index 0000000..05ab188 --- /dev/null +++ b/lab3/utils/genKernel.pl @@ -0,0 +1,13 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 100000); + +print STDERR "OK: Kernel is $n bytes - Extended to 200 sectors\n"; + +$buf .= "\0" x (102400-$n); + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/lab4/Makefile b/lab4/Makefile new file mode 100644 index 0000000..1b2eaa5 --- /dev/null +++ b/lab4/Makefile @@ -0,0 +1,19 @@ +QEMU = qemu-system-i386 + +os.img: + @cd bootloader; make + @cd kernel; make + @cd app; make + cat bootloader/bootloader.bin kernel/kMain.elf app/uMain.elf > os.img + +play: os.img + $(QEMU) -serial stdio os.img + +debug: os.img + $(QEMU) -serial stdio -s -S os.img + +clean: + @cd bootloader; make clean + @cd kernel; make clean + @cd app; make clean + rm -f os.img diff --git a/lab4/app/Makefile b/lab4/app/Makefile new file mode 100644 index 0000000..259f8bf --- /dev/null +++ b/lab4/app/Makefile @@ -0,0 +1,17 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 -I../lib +LDFLAGS = -m elf_i386 + +UCFILES = $(shell find ./ -name "*.c") +LCFILES = $(shell find ../lib -name "*.c") +UOBJS = $(UCFILES:.c=.o) $(LCFILES:.c=.o) + +umain.bin: $(UOBJS) + $(LD) $(LDFLAGS) -e uEntry -Ttext 0x00200000 -o uMain.elf $(UOBJS) + +clean: + rm -rf $(UOBJS) uMain.elf diff --git a/lab4/app/main.c b/lab4/app/main.c new file mode 100644 index 0000000..8e1211d --- /dev/null +++ b/lab4/app/main.c @@ -0,0 +1,43 @@ +#include "lib.h" +#include "types.h" + +int uEntry(void) { + int i = 4; + int ret = 0; + int value = 2; + + sem_t sem; + printf("Father Process: Semaphore Initializing.\n"); + ret = sem_init(&sem, value); + if (ret == -1) { + printf("Father Process: Semaphore Initializing Failed.\n"); + exit(); + } + + ret = fork(); + if (ret == 0) { + while( i != 0) { + i --; + printf("Child Process: Semaphore Waiting.\n"); + sem_wait(&sem); + printf("Child Process: In Critical Area.\n"); + } + printf("Child Process: Semaphore Destroying.\n"); + sem_destroy(&sem); + exit(); + } + else if (ret != -1) { + while( i != 0) { + i --; + printf("Father Process: Sleeping.\n"); + sleep(128); + printf("Father Process: Semaphore Posting.\n"); + sem_post(&sem); + } + printf("Father Process: Semaphore Destroying.\n"); + sem_destroy(&sem); + exit(); + } + + return 0; +} diff --git a/lab4/bootloader/Makefile b/lab4/bootloader/Makefile new file mode 100644 index 0000000..76fa6e5 --- /dev/null +++ b/lab4/bootloader/Makefile @@ -0,0 +1,20 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 +ASFLAGS = -m32 +LDFLAGS = -m elf_i386 + +BSFILES = $(shell find ./ -name "*.S") +BCFILES = $(shell find ./ -name "*.c") +BOBJS = $(BSFILES:.S=.o) $(BCFILES:.c=.o) + +bootloader.bin: $(BOBJS) + $(LD) $(LDFLAGS) -e start -Ttext 0x7c00 -o bootloader.elf $(BOBJS) + objcopy -O binary bootloader.elf bootloader.bin + @../utils/genBoot.pl bootloader.bin + +clean: + rm -rf $(BOBJS) bootloader.elf bootloader.bin diff --git a/lab4/bootloader/boot.c b/lab4/bootloader/boot.c new file mode 100644 index 0000000..430e957 --- /dev/null +++ b/lab4/bootloader/boot.c @@ -0,0 +1,55 @@ +#include "boot.h" +#include + +#define SECTSIZE 512 +#define MAXNUM 200 +#define BUFSIZE (SECTSIZE*MAXNUM) + +#define NULL ((void *)0) + +void bootMain(void) { + /* 加载内核至内存,并跳转执行 */ + void (*kernel) (void); + + ELFHeader *elf; + ProgramHeader *ph; + + unsigned char buf[BUFSIZE]; + + int i=0; + for(i=0; i < MAXNUM; i++) + readSect((void *)(buf + i*SECTSIZE), i+1); + + elf = (void *)buf; + for(i=0; i < elf->phnum; i++){ + ph = (ProgramHeader *)(buf + elf->phoff + i * elf->phentsize); + int vaddr = ph->vaddr; + int filesz = ph->filesz; + memcpy((void *)vaddr, buf+ph->off, filesz); + memset((void *)(vaddr+filesz), 0, ph->memsz-filesz); + } + kernel = (void *)elf->entry; + kernel(); +} + +void waitDisk(void) { // waiting for disk + while((inByte(0x1F7) & 0xC0) != 0x40); +} + +void readSect(void *dst, int offset) { // reading a sector of disk + int i; + waitDisk(); + outByte(0x1F2, 1); + outByte(0x1F3, offset); + outByte(0x1F4, offset >> 8); + outByte(0x1F5, offset >> 16); + outByte(0x1F6, (offset >> 24) | 0xE0); + outByte(0x1F7, 0x20); + + waitDisk(); + for (i = 0; i < SECTSIZE / 4; i ++) { + ((int *)dst)[i] = inLong(0x1F0); + } +} + + diff --git a/lab4/bootloader/boot.h b/lab4/bootloader/boot.h new file mode 100644 index 0000000..b313576 --- /dev/null +++ b/lab4/bootloader/boot.h @@ -0,0 +1,59 @@ +#ifndef BOOT_H +#define BOOT_H + + +struct ELFHeader { + unsigned int magic; + unsigned char elf[12]; + unsigned short type; + unsigned short machine; + unsigned int version; + unsigned int entry; + unsigned int phoff; + unsigned int shoff; + unsigned int flags; + unsigned short ehsize; + unsigned short phentsize; + unsigned short phnum; + unsigned short shentsize; + unsigned short shnum; + unsigned short shstrndx; +}; + +/* ELF32 Program header */ +struct ProgramHeader { + unsigned int type; + unsigned int off; + unsigned int vaddr; + unsigned int paddr; + unsigned int filesz; + unsigned int memsz; + unsigned int flags; + unsigned int align; +}; + +typedef struct ELFHeader ELFHeader; +typedef struct ProgramHeader ProgramHeader; + +void waitDisk(void); + +void readSect(void *dst, int offset); + +/* I/O functions */ +static inline char inByte(short port) { + char data; + asm volatile("in %1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static inline int inLong(short port) { + int data; + asm volatile("in %1, %0" : "=a" (data) : "d" (port)); + return data; +} + +static inline void outByte(short port, char data) { + asm volatile("out %0,%1" : : "a" (data), "d" (port)); +} + +#endif diff --git a/lab4/bootloader/start.S b/lab4/bootloader/start.S new file mode 100644 index 0000000..7e340f2 --- /dev/null +++ b/lab4/bootloader/start.S @@ -0,0 +1,37 @@ +.code16 + +.global start +start: + cli #关闭中断 + inb $0x92, %al #启动A20总线 + orb $0x02, %al + outb %al, $0x92 + data32 addr32 lgdt gdtDesc #加载GDTR + movl %cr0, %eax #启动保护模式 + orb $0x01, %al + movl %eax, %cr0 + data32 ljmp $0x08, $start32 #长跳转切换至保护 + +.code32 +start32: + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movl $(128<<20), %esp + jmp bootMain + +.p2align 2 +gdt: # each table entry, at least 1 entry + .word 0,0 # empty entry + .byte 0,0,0,0 + + .word 0xffff,0 + .byte 0,0x9a,0xcf,0 + + .word 0xffff,0 + .byte 0,0x92,0xcf,0 + +gdtDesc: # 6 bytes in total + .word (gdtDesc - gdt -1) + .long gdt diff --git a/lab4/kernel/Makefile b/lab4/kernel/Makefile new file mode 100644 index 0000000..1dabd77 --- /dev/null +++ b/lab4/kernel/Makefile @@ -0,0 +1,20 @@ +CC = gcc +LD = ld + +CFLAGS = -m32 -march=i386 -static \ + -fno-builtin -fno-stack-protector -fno-omit-frame-pointer \ + -Wall -Werror -O2 -I./include +ASFLAGS = -m32 +LDFLAGS = -m elf_i386 + +KCFILES = $(shell find ./ -name "*.c") +KSFILES = $(shell find ./ -name "*.S") +KOBJS = $(KCFILES:.c=.o) $(KSFILES:.S=.o) + +kmain.bin: $(KOBJS) + $(LD) $(LDFLAGS) -e kEntry -Ttext 0x00100000 -o kMain.elf $(KOBJS) + @../utils/genKernel.pl kMain.elf + + +clean: + rm -rf $(KOBJS) kMain.elf kMain.bin diff --git a/lab4/kernel/include/common.h b/lab4/kernel/include/common.h new file mode 100644 index 0000000..f3f8b1d --- /dev/null +++ b/lab4/kernel/include/common.h @@ -0,0 +1,8 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "common/types.h" +#include "common/const.h" +#include "common/assert.h" + +#endif diff --git a/lab4/kernel/include/common/assert.h b/lab4/kernel/include/common/assert.h new file mode 100644 index 0000000..8c5e9bd --- /dev/null +++ b/lab4/kernel/include/common/assert.h @@ -0,0 +1,10 @@ +#ifndef __ASSERT_H__ +#define __ASSERT_H__ + +int abort(const char *, int); + +/* assert: 断言条件为真,若为假则蓝屏退出 */ +#define assert(cond) \ + ((cond) ? (0) : (abort(__FILE__, __LINE__))) + +#endif diff --git a/lab4/kernel/include/common/const.h b/lab4/kernel/include/common/const.h new file mode 100644 index 0000000..7a3f9eb --- /dev/null +++ b/lab4/kernel/include/common/const.h @@ -0,0 +1,9 @@ +#ifndef __CONST_H__ +#define __CONST_H__ + +#define TRUE 1 +#define FALSE 0 + +#define NULL ((void*)0) + +#endif diff --git a/lab4/kernel/include/common/types.h b/lab4/kernel/include/common/types.h new file mode 100644 index 0000000..ba71de2 --- /dev/null +++ b/lab4/kernel/include/common/types.h @@ -0,0 +1,15 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +/* 定义数据类型 */ +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned int size_t; + +#define PT_LOAD 1 + +#endif diff --git a/lab4/kernel/include/device.h b/lab4/kernel/include/device.h new file mode 100644 index 0000000..32dbdf2 --- /dev/null +++ b/lab4/kernel/include/device.h @@ -0,0 +1,6 @@ +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +#include "device/serial.h" + +#endif diff --git a/lab4/kernel/include/device/serial.h b/lab4/kernel/include/device/serial.h new file mode 100644 index 0000000..2c71d57 --- /dev/null +++ b/lab4/kernel/include/device/serial.h @@ -0,0 +1,8 @@ +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + +void initSerial(void); +void putChar(char); +#define SERIAL_PORT 0x3F8 + +#endif diff --git a/lab4/kernel/include/x86.h b/lab4/kernel/include/x86.h new file mode 100644 index 0000000..91f2ce6 --- /dev/null +++ b/lab4/kernel/include/x86.h @@ -0,0 +1,13 @@ +#ifndef __X86_H__ +#define __X86_H__ + +#include "x86/cpu.h" +#include "x86/memory.h" +#include "x86/io.h" +#include "x86/irq.h" +#include "x86/debug.h" + +void initSeg(void); +uint32_t loadUMain(void); + +#endif diff --git a/lab4/kernel/include/x86/cpu.h b/lab4/kernel/include/x86/cpu.h new file mode 100644 index 0000000..744facd --- /dev/null +++ b/lab4/kernel/include/x86/cpu.h @@ -0,0 +1,32 @@ +#ifndef __X86_CPU_H__ +#define __X86_CPU_H__ + +#include "common.h" + +/* 将CPU置入休眠状态直到下次中断到来 */ +static inline void waitForInterrupt() { + asm volatile("hlt"); +} + +/* 修改IDTR */ +static inline void saveIdt(void *addr, uint32_t size) { + static volatile uint16_t data[3]; + data[0] = size - 1; + data[1] = (uint32_t)addr; + data[2] = ((uint32_t)addr) >> 16; + asm volatile("lidt (%0)" : : "r"(data)); +} + +/* 打开外部中断 */ +static inline void enableInterrupt(void) { + asm volatile("sti"); +} + +/* 关闭外部中断 */ +static inline void disableInterrupt(void) { + asm volatile("cli"); +} + +#define NR_IRQ 256 + +#endif diff --git a/lab4/kernel/include/x86/debug.h b/lab4/kernel/include/x86/debug.h new file mode 100644 index 0000000..e3c627c --- /dev/null +++ b/lab4/kernel/include/x86/debug.h @@ -0,0 +1,29 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#define DEBUG + +int putString(char *buf); +int putNum(int k, int hex); +void putTF(struct TrapFrame* tf); +void putPCB(struct ProcessTable *p); +void putList(struct ProcessTable *list); + +#ifdef DEBUG +#define LOG_STRING(str) putString(str) +#define LOG_NUM(k, hex) putNum(k, hex) +#define LOG_TF(tf) putTF(tf) +#define LOG_PCB(p) putPCB(p) +#define LOG_LIST(list) putList(list) + +#else +#define LOG_STRING(str) +#define LOG_NUM(k, hex) +#define LOG_TF(tf) +#define LOG_PCB(p) +#define LOG_LIST(list) + +#endif + + +#endif diff --git a/lab4/kernel/include/x86/io.h b/lab4/kernel/include/x86/io.h new file mode 100644 index 0000000..5fad01e --- /dev/null +++ b/lab4/kernel/include/x86/io.h @@ -0,0 +1,56 @@ +#ifndef __X86_IO_H__ +#define __X86_IO_H__ +/* ELF32二进制文件头 */ +struct ELFHeader { + unsigned int magic; + unsigned char elf[12]; + unsigned short type; + unsigned short machine; + unsigned int version; + unsigned int entry; + unsigned int phoff; + unsigned int shoff; + unsigned int flags; + unsigned short ehsize; + unsigned short phentsize; + unsigned short phnum; + unsigned short shentsize; + unsigned short shnum; + unsigned short shstrndx; +}; + +/* ELF32 Program header */ +struct ProgramHeader { + unsigned int type; + unsigned int off; + unsigned int vaddr; + unsigned int paddr; + unsigned int filesz; + unsigned int memsz; + unsigned int flags; + unsigned int align; +}; + +typedef struct ELFHeader ELFHeader; +typedef struct ProgramHeader ProgramHeader; + + +static inline int inLong(short port) { + int data; + asm volatile("in %1, %0" : "=a" (data) : "d" (port)); + return data; +} + +/* 读I/O端口 */ +static inline uint8_t inByte(uint16_t port) { + uint8_t data; + asm volatile("in %1, %0" : "=a"(data) : "d"(port)); + return data; +} + +/* 写I/O端口 */ +static inline void outByte(uint16_t port, int8_t data) { + asm volatile("out %%al, %%dx" : : "a"(data), "d"(port)); +} + +#endif diff --git a/lab4/kernel/include/x86/irq.h b/lab4/kernel/include/x86/irq.h new file mode 100644 index 0000000..4d2c161 --- /dev/null +++ b/lab4/kernel/include/x86/irq.h @@ -0,0 +1,8 @@ +#ifndef __IRQ_H__ +#define __IRQ_H__ + +/* 中断处理相关函数 */ +void initIdt(void); +void initIntr(void); + +#endif diff --git a/lab4/kernel/include/x86/memory.h b/lab4/kernel/include/x86/memory.h new file mode 100644 index 0000000..7030460 --- /dev/null +++ b/lab4/kernel/include/x86/memory.h @@ -0,0 +1,177 @@ +#ifndef __X86_MEMORY_H__ +#define __X86_MEMORY_H__ + +#define DPL_KERN 0 +#define DPL_USER 3 + +// Application segment type bits +#define STA_X 0x8 // Executable segment +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) + +// System segment type bits +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate + +// GDT entries +#define NR_SEGMENTS 9 // GDT size +#define SEG_KCODE 1 // Kernel code +#define SEG_KDATA 2 // Kernel data/stack +#define SEG_UCODE 3 // User code +#define SEG_UDATA 4 // User data/stack +#define SEG_TSS 5 // Global unique task state segement + +// Selectors +#define KSEL(desc) (((desc) << 3) | DPL_KERN) +#define USEL(desc) (((desc) << 3) | DPL_USER) + +int current_index; +int current_base; + +struct GateDescriptor { + uint32_t offset_15_0 : 16; + uint32_t segment : 16; + uint32_t pad0 : 8; + uint32_t type : 4; + uint32_t system : 1; + uint32_t privilege_level : 2; + uint32_t present : 1; + uint32_t offset_31_16 : 16; +}; + +typedef struct GateDescriptor GateDescriptor; + +/* +struct TrapFrame { + uint32_t edi, esi, ebp, xxx, ebx, edx, ecx, eax; + int32_t irq; +};*/ + +/* +1. The number of bits in a bit field sets the limit to the range of values it can hold +2. Multiple adjacent bit fields are usually packed together (although this behavior is implementation-defined) + +Refer: en.cppreference.com/w/cpp/language/bit_field +*/ +struct SegDesc { + uint32_t lim_15_0 : 16; // Low bits of segment limit + uint32_t base_15_0 : 16; // Low bits of segment base address + uint32_t base_23_16 : 8; // Middle bits of segment base address + uint32_t type : 4; // Segment type (see STS_ constants) + uint32_t s : 1; // 0 = system, 1 = application + uint32_t dpl : 2; // Descriptor Privilege Level + uint32_t p : 1; // Present + uint32_t lim_19_16 : 4; // High bits of segment limit + uint32_t avl : 1; // Unused (available for software use) + uint32_t rsv1 : 1; // Reserved + uint32_t db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + uint32_t g : 1; // Granularity: limit scaled by 4K when set + uint32_t base_31_24 : 8; // High bits of segment base address +}; +typedef struct SegDesc SegDesc; + +#define SEG(type, base, lim, dpl) (SegDesc) \ +{ ((lim) >> 12) & 0xffff, (uint32_t)(base) & 0xffff, \ + ((uint32_t)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uint32_t)(lim) >> 28, 0, 0, 1, 1, (uint32_t)(base) >> 24 } + +#define SEG16(type, base, lim, dpl) (SegDesc) \ +{ (lim) & 0xffff, (uint32_t)(base) & 0xffff, \ + ((uint32_t)(base) >> 16) & 0xff, type, 0, dpl, 1, \ + (uint32_t)(lim) >> 16, 0, 0, 1, 0, (uint32_t)(base) >> 24 } + +// Task state segment format +struct TSS { + uint32_t link; // old ts selector + uint32_t esp0; // Ring 0 Stack pointer and segment selector + uint32_t ss0; // after an increase in privilege level + union{ + struct{ + char dontcare[88]; + }; + struct{ + uint32_t esp1,ss1,esp2,ss2; + uint32_t cr3, eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; + uint32_t es, cs, ss, ds, fs, gs, ldt; + }; + }; +}; +typedef struct TSS TSS; + +SegDesc gdt[NR_SEGMENTS]; +TSS tss; + +#define MAX_STACK_SIZE 0x2000 +#define MAX_PCB_NUM 32 +#define TASK_FREE 0 +#define TASK_RUNNING 1 +#define TASK_RUNNABLE 2 +#define TASK_SLEEP 3 +#define TASK_BLOCKED 4 +#define TASK_DEAD 5 + + + +struct TrapFrame { + uint32_t gs, fs, es, ds; + uint32_t edi, esi, ebp, xxx, ebx, edx, ecx, eax; + uint32_t irq; + uint32_t error; + uint32_t eip, cs, eflags, esp, ss; +}; + +struct ProcessTable{ + struct TrapFrame *tf; + int state; + int timeCount; + int sleepTime; + uint32_t pid; + struct ProcessTable *link; + int sem_list; + uint32_t stack[MAX_STACK_SIZE]; +}; +typedef struct ProcessTable PCB; +struct ProcessTable pcb[MAX_PCB_NUM]; +struct ProcessTable *current; +struct ProcessTable *run_list;//runnable list +int next_pcb; +int nr_process; +int need_resched; + +#define GDT_BASE(i) ((uint32_t)(gdt[i].base_15_0 + (gdt[i].base_23_16<<16) + (gdt[i].base_31_24 << 24))) + + +#define MAX_SEM_NUM 32 +#define SEM_VALID 1 +#define SEM_USED 0 + +struct Semaphore { + int value; + struct ProcessTable *list; //process blocked on this semaphore + int state; //valid when 1, else invalid + int linkCount; //link count, this sem will be destroied only when linkCoutn == 1 + int next; //next semaphore +}; +typedef struct Semaphore Semaphore; +Semaphore sem[MAX_SEM_NUM]; +int next_sem; + +void P(Semaphore *s); +void V(Semaphore *s); + + +static inline void setGdt(SegDesc *gdt, uint32_t size) { + volatile static uint16_t data[3]; + data[0] = size - 1; + data[1] = (uint32_t)gdt; + data[2] = (uint32_t)gdt >> 16; + asm volatile("lgdt (%0)" : : "r"(data)); +} + +static inline void lLdt(uint16_t sel) +{ + asm volatile("lldt %0" :: "r"(sel)); +} + +#endif diff --git a/lab4/kernel/kernel/debug.c b/lab4/kernel/kernel/debug.c new file mode 100644 index 0000000..f12fe0a --- /dev/null +++ b/lab4/kernel/kernel/debug.c @@ -0,0 +1,78 @@ +#include "x86.h" + + +void putChar(char ch); + + +int itoa(int k, char *str, int hex) +{ + int i, j, n, base, sign; + char buf[32]; + if((k < 0) && hex == 10) { + sign = -1; + k = -k; + } + else sign = 1; + unsigned num = (unsigned)k; + i = 0; base = hex; + do{ + n = num % base; + if(n >= 0 && n <= 9) buf[i++] = n + '0'; + else buf[i++] = n + 'a'-10; + } while((num = num/base) > 0); + if(sign < 0) buf[i++] = '-'; + for(j=0; j < i; j++) + str[j] = buf[i-j-1]; + return i; +} + +int putString(char *buf) +{ + char *p = buf; + while(*p != '\0'){ + putChar(*p); + p++; + } + return (int)(p-buf); +} + +int putNum(int k, int hex) +{ + int i; + char buf[32]; + int len = itoa(k, buf, hex); + for(i=0; i < len; i++){ + putChar(buf[i]); + } + return len; +} + +void putTF(struct TrapFrame* tf) +{ + putString("%ds=0x"); putNum(tf->ds, 16); putString(" "); + putString("%cs=0x"); putNum(tf->cs, 16); putString(" "); + putString("%ss=0x"); putNum(tf->ss, 16); putString("\n"); + putString("%eip=0x"); putNum(tf->eip, 16); putString(" "); + putString("%esp=0x"); putNum(tf->esp, 16); putString(" "); + putString("irq=0x"); putNum(tf->irq, 16); putString("\n"); +} + +void putPCB(struct ProcessTable *p) +{ + putTF(p->tf); + putString("pid=0x"); putNum(p->pid, 16); putString(" "); + putString("state=0x"); putNum(p->state, 16); putString(" "); + putString("timeCount=0x"); putNum(p->timeCount, 16); putString(" "); + putString("sleepTime=0x"); putNum(p->sleepTime, 16); putString("\n"); +} + +void putList(struct ProcessTable *list) +{ + int i = 0; + struct ProcessTable *p = list; + while(p != NULL){ + putString("i="); putNum(i, 10); putString(", "); + putString("pid="); putNum(p->pid, 10); putString("\n"); + p = p->link; i++; + } +} diff --git a/lab4/kernel/kernel/doIrq.S b/lab4/kernel/kernel/doIrq.S new file mode 100644 index 0000000..70cf2cf --- /dev/null +++ b/lab4/kernel/kernel/doIrq.S @@ -0,0 +1,50 @@ +.code32 + +.global irqEmpty +irqEmpty: + pushl $0 // push dummy error code + pushl $-1 // push interrupt vector into kernel + jmp asmDoIrq + +.global irqGProtectFault +irqGProtectFault: + pushl $0xd + jmp asmDoIrq + +.global irqSyscall +irqSyscall: + pushl $0 // push dummy error code + pushl $0x80 // push interrupt vector into kernel stack + jmp asmDoIrq + +.global irqTime +irqTime: + pushl $0 + pushl $0x20 + jmp asmDoIrq + +.extern current + +.global asmDoIrq +asmDoIrq: + cli + pushal // push process state into kernel stack + pushl %ds + pushl %es + pushl %fs + pushl %gs + pushl %esp + movl $0x10, %eax + movl %eax, %ds + movl %eax, %es + call irqHandle + movl (current), %eax + movl (%eax), %esp + popl %gs + popl %fs + popl %es + popl %ds + popal + addl $4, %esp //interrupt vector is on top of kernel stack + addl $4, %esp //error code is on top of kernel stack + iret diff --git a/lab4/kernel/kernel/i8259.c b/lab4/kernel/kernel/i8259.c new file mode 100644 index 0000000..7e50866 --- /dev/null +++ b/lab4/kernel/kernel/i8259.c @@ -0,0 +1,26 @@ +#include "x86.h" + +#define PORT_PIC_MASTER 0x20 +#define PORT_PIC_SLAVE 0xA0 +#define IRQ_SLAVE 2 + +/* 初始化8259中断控制器: + * 硬件中断IRQ从32号开始,自动发送EOI */ +void +initIntr(void) { + outByte(PORT_PIC_MASTER + 1, 0xFF); + outByte(PORT_PIC_SLAVE + 1 , 0xFF); + outByte(PORT_PIC_MASTER, 0x11); // Initialization command + outByte(PORT_PIC_MASTER + 1, 32); // Interrupt Vector Offset 0x20 + outByte(PORT_PIC_MASTER + 1, 1 << 2); // Tell Master PIC that there is a slave + outByte(PORT_PIC_MASTER + 1, 0x3); // Auto EOI in 8086/88 mode + outByte(PORT_PIC_SLAVE, 0x11); // Initialization command + outByte(PORT_PIC_SLAVE + 1, 32 + 8); // Interrupt Vector Offset 0x28 + outByte(PORT_PIC_SLAVE + 1, 2); // Tell Slave PIC its cascade identity + outByte(PORT_PIC_SLAVE + 1, 0x3); // Auto EOI in 8086/88 mode + + outByte(PORT_PIC_MASTER, 0x68); + outByte(PORT_PIC_MASTER, 0x0A); + outByte(PORT_PIC_SLAVE, 0x68); + outByte(PORT_PIC_SLAVE, 0x0A); +} diff --git a/lab4/kernel/kernel/idle.c b/lab4/kernel/kernel/idle.c new file mode 100644 index 0000000..edf1250 --- /dev/null +++ b/lab4/kernel/kernel/idle.c @@ -0,0 +1,98 @@ +#include "x86.h" +//#include + +struct ProcessTable pcb[MAX_PCB_NUM]; +struct ProcessTable idle_pcb; +struct ProcessTable *current;//the task is running +struct ProcessTable *run_list;//runnable list +int nr_process;//number of process +int need_resched;//if need reschedule +struct TSS tss; + +int puts(char *buf, int len); + +struct ProcessTable* add_to_queue(struct ProcessTable * list, struct ProcessTable *m) +{ + struct ProcessTable *pre = list; + if(pre == NULL){ + m->link = NULL; + list = m; + } + else{ + for(; pre->link; pre=pre->link); + pre->link = m; + m->link = NULL; + } + return list; +} + +struct ProcessTable* del_to_queue(struct ProcessTable * list, struct ProcessTable *m) +{ + struct ProcessTable *pre = list; + if(!list) return list; + if(list == m){ + list = list->link; + pre->link = NULL; + } + else{ + for(; pre->link && pre->link != m; pre=pre->link); + if(pre->link == m){ + struct ProcessTable *tmp = pre->link; + pre->link = tmp->link; + tmp->link = NULL; + } + } + return list; +} + +void idle() +{ + if(nr_process != 0) + enableInterrupt(); + waitForInterrupt(); +} + +void initPCB() +{ + int i; + for(i=0; i < MAX_PCB_NUM; i++){ + pcb[i].state = TASK_FREE; + pcb[i].timeCount = 0; + pcb[i].sleepTime = 0; + pcb[i].pid = -1; + pcb[i].sem_list = -1; + } + current = NULL; + run_list = NULL; + nr_process = 0; + next_pcb = 0; + need_resched = 0;//if need reschedule +} + +struct ProcessTable* initUserProcess(uint32_t entry) +{ + int i = next_pcb++; + pcb[i].state = TASK_RUNNABLE; + pcb[i].timeCount = 20; + pcb[i].sleepTime = 0; + pcb[i].pid = 1; + + pcb[i].tf = (struct TrapFrame *)(pcb[0].stack + MAX_STACK_SIZE) - 1; + + pcb[i].tf->eip = entry; + pcb[i].tf->cs = USEL(SEG_UCODE); + pcb[i].tf->eflags = 0x202; + pcb[i].tf->esp = 0x400000; + pcb[i].tf->ss = USEL(SEG_UDATA); + pcb[i].tf->ds = USEL(SEG_UDATA); + pcb[i].tf->es = USEL(SEG_UDATA); + run_list = add_to_queue(run_list, &pcb[i]); + need_resched = 1; + nr_process ++; + + return &pcb[0]; +} + + + + diff --git a/lab4/kernel/kernel/idt.c b/lab4/kernel/kernel/idt.c new file mode 100644 index 0000000..3b07914 --- /dev/null +++ b/lab4/kernel/kernel/idt.c @@ -0,0 +1,58 @@ +#include "x86.h" +#include "device.h" + +#define INTERRUPT_GATE_32 0xE +#define TRAP_GATE_32 0xF + +/* IDT表的内容 */ +struct GateDescriptor idt[NR_IRQ]; // NR_IRQ=256, defined in x86/cpu.h + +/* 初始化一个中断门(interrupt gate) */ +static void setIntr(struct GateDescriptor *ptr, uint32_t selector, uint32_t offset, uint32_t dpl) { + ptr->offset_15_0 = offset & 0xFFFF; + ptr->segment = selector << 3; + ptr->pad0 = 0; + ptr->type = INTERRUPT_GATE_32; + ptr->system = FALSE; + ptr->privilege_level = dpl; + ptr->present = TRUE; + ptr->offset_31_16 = (offset >> 16) & 0xFFFF; +} + +/* 初始化一个陷阱门(trap gate) */ +static void setTrap(struct GateDescriptor *ptr, uint32_t selector, uint32_t offset, uint32_t dpl) { + ptr->offset_15_0 = offset & 0xFFFF; + ptr->segment = selector << 3; + ptr->pad0 = 0; + ptr->type = TRAP_GATE_32; + ptr->system = FALSE; + ptr->privilege_level = dpl; + ptr->present = TRUE; + ptr->offset_31_16 = (offset >> 16) & 0xFFFF; +} + +/* 声明函数,这些函数在汇编代码里定义 */ +void irqEmpty(); +void irqGProtectFault(); +void irqSyscall(); +void irqTime(); + +void initIdt() { + int i; + /* 为了防止系统异常终止,所有irq都有处理函数(irqEmpty)。 */ + for (i = 0; i < NR_IRQ; i ++) { + setTrap(idt + i, SEG_KCODE, (uint32_t)irqEmpty, DPL_KERN); + } + /* + * init your idt here + * 初始化 IDT 表, 为中断设置中断处理函数 + */ + + setTrap(idt + 0xd, SEG_KCODE, (uint32_t)irqGProtectFault, DPL_KERN); + + setIntr(idt + 0x80, SEG_KCODE, (uint32_t)irqSyscall, DPL_USER); // for int 0x80, interrupt vector is 0x80, Interruption is disabled + setIntr(idt + 0x20, SEG_KCODE, (uint32_t)irqTime, DPL_USER); // for int 0x80, interrupt vector is 0x80, Interruption is disabled + + /* 写入IDT */ + saveIdt(idt, sizeof(idt)); +} diff --git a/lab4/kernel/kernel/irqHandle.c b/lab4/kernel/kernel/irqHandle.c new file mode 100644 index 0000000..7b9ac18 --- /dev/null +++ b/lab4/kernel/kernel/irqHandle.c @@ -0,0 +1,212 @@ +#include "x86.h" +#include "device.h" +#include + +#define SYS_EXIT 1 +#define SYS_FORK 2 +#define SYS_SLEEP 3 +#define SYS_WRITE 4 +#define SEM_CREAT 7 +#define SEM_INIT 8 +#define SEM_POST 9 +#define SEM_WAIT 10 +#define SEM_DESTROY 11 + +#define G_PORT (0xb800) + +SegDesc gdt[NR_SEGMENTS]; +TSS tss; + +void syscallHandle(struct TrapFrame *tf); + +void GProtectFaultHandle(struct TrapFrame *tf); + +void TimeBreakHandle(struct TrapFrame *tf); + +int puts(char *, int); + +struct ProcessTable* add_to_queue(struct ProcessTable * list, struct ProcessTable *m); +struct ProcessTable* del_to_queue(struct ProcessTable * list, struct ProcessTable *m); +void schedule(); +void idle(); + +void sem_creat(struct TrapFrame *tf); +void sem_init(struct TrapFrame *tf); +void sem_post(struct TrapFrame *tf); +void sem_wait(struct TrapFrame *tf); +void sem_destroy(struct TrapFrame *tf); + +void irqHandle(struct TrapFrame *tf) { + /* + * 中断处理程序 + */ + /* Reassign segment register */ + disableInterrupt(); + + LOG_LIST(run_list); + + if(current != NULL){ + memcpy(current->tf, tf, sizeof(struct TrapFrame)); + LOG_PCB(current); + } + + switch(tf->irq) { + case -1: + break; + case 0xd: + GProtectFaultHandle(tf); + break; + case 0x20: + TimeBreakHandle(tf); + break; + case 0x80: + syscallHandle(tf); + break; + default: + assert(0); + } + if(need_resched == 1) + schedule(); + if(current == NULL) idle(); + LOG_STRING("-------------------\n"); + +} + +static void sys_write(struct TrapFrame *tf) +{ + int fd = (tf->ebx); + uint32_t segBase = (uint32_t )(gdt[tf->ds >> 3].base_15_0 + (gdt[tf->ds>>3].base_23_16<<16) + (gdt[tf->ds >> 3].base_31_24 << 24)); + assert(tf->edx != 0); + char *buf = (char *)(tf->ecx + segBase); + int len = tf->edx; + if(fd == 1) + puts(buf, len); + else + assert(0); +} + +static void sys_exit(struct TrapFrame *tf) +{ + current->state = TASK_FREE; + need_resched = 1; + + nr_process--; + return; +} + +static void sys_fork(struct TrapFrame *tf) +{ + int i; + uint32_t *father_start = (uint32_t *)GDT_BASE(tf->ds>>3);//(uint32_t *)(gdt[tf->ds >> 3].base_15_0 + (gdt[tf->ds>>3].base_23_16<<16) + (gdt[tf->ds >> 3].base_31_24 << 24)); + uint32_t newSegBase = current_base; + current_base += 0x400000; + uint32_t *cd_start = (uint32_t *)newSegBase; + memcpy(cd_start, father_start, 0x400000); + struct ProcessTable *newpcb = &pcb[next_pcb++]; + memcpy(newpcb->stack, current->stack, MAX_STACK_SIZE*sizeof(uint32_t)); + newpcb->tf = (struct TrapFrame *)(newpcb->stack + MAX_STACK_SIZE) - 1; + memcpy(newpcb->tf, tf, sizeof(struct TrapFrame)); + newpcb->tf->eax = 0; //child process return 0 + current->tf->eax = 2; //father process return pid of child + //creat new gdt + int newSegCodeIndex = current_index++; + int newSegDataIndex = current_index++; + gdt[newSegCodeIndex] = SEG(STA_X | STA_R, newSegBase, 0x400000, DPL_USER); + gdt[newSegDataIndex] = SEG(STA_W, newSegBase, 0x400000, DPL_USER); + newpcb->tf->es = USEL(newSegDataIndex); + newpcb->tf->ss = USEL(newSegDataIndex); + newpcb->tf->ds = USEL(newSegDataIndex); + newpcb->tf->gs = USEL(newSegDataIndex); + newpcb->tf->cs = USEL(newSegCodeIndex); + newpcb->state = TASK_RUNNABLE; + newpcb->timeCount = 10; + newpcb->pid = next_pcb; + run_list = add_to_queue(run_list, newpcb); + nr_process++; + for(i=current->sem_list; i >=0 ;i=sem[i].next) + sem[i].linkCount ++; + + return; +} + +static void sys_sleep(struct TrapFrame *tf) +{ + current->state = TASK_SLEEP; + current->sleepTime = tf->ecx; + need_resched = 1; + + return; +} + +void syscallHandle(struct TrapFrame *tf) { + /* 实现系统调用*/ + + LOG_STRING("syscall: nr=0x"); + LOG_NUM(tf->eax, 16); + LOG_STRING("\n"); + + switch(tf->eax){ + case SYS_WRITE: sys_write(tf); break; + case SYS_FORK: sys_fork(tf); break; + case SYS_EXIT: sys_exit(tf); break; + case SYS_SLEEP: sys_sleep(tf); break; + case SEM_CREAT: sem_creat(tf); break; + case SEM_INIT: sem_init(tf); break; + case SEM_POST: sem_post(tf); break; + case SEM_WAIT: sem_wait(tf); break; + case SEM_DESTROY: sem_destroy(tf); break; + default: assert(0); + } +} + +void GProtectFaultHandle(struct TrapFrame *tf){ + assert(0); + return; +} + + +void TimeBreakHandle(struct TrapFrame *tf) +{ + int i; + for(i=0; i < MAX_PCB_NUM; i++){ + if(pcb[i].state == TASK_RUNNING){ + pcb[i].timeCount --; + if(pcb[i].timeCount <= 0){ + pcb[i].state = TASK_RUNNABLE; + run_list = add_to_queue(run_list, &pcb[i]); + need_resched = 1; + } + } + else if(pcb[i].state == TASK_SLEEP){ + pcb[i].sleepTime --; + if(pcb[i].sleepTime == 0){ + pcb[i].state = TASK_RUNNABLE; + pcb[i].timeCount = 10; + run_list = add_to_queue(run_list, &pcb[i]); + need_resched = 1; + } + + } + } + return ; +} + +int puts(char *buf, int len) +{ + char *p1 = (char *)0xb8000; + char *p2 = buf; + static int off = 640; + int i; + for(i=0; i < len; i++){ + if(*p2 == '\n'){ + off = (off/160+1)*160; + p2 ++; + } + else{ + *(p1+off) = *(p2++); + *(p1+off+1) = 0x0c; + off += 2; + } + } + return p2-buf; +} diff --git a/lab4/kernel/kernel/kvm.c b/lab4/kernel/kernel/kvm.c new file mode 100644 index 0000000..9bfc593 --- /dev/null +++ b/lab4/kernel/kernel/kvm.c @@ -0,0 +1,117 @@ +#include "x86.h" +#include "device.h" +#include + +SegDesc gdt[NR_SEGMENTS]; +TSS tss; + +#define SECTSIZE 512 +#define NUM 200 +#define BUFSIZE (SECTSIZE*NUM) + +void waitDisk(void) { + while((inByte(0x1F7) & 0xC0) != 0x40); +} + +void readSect(void *dst, int offset) { + int i; + waitDisk(); + + outByte(0x1F2, 1); + outByte(0x1F3, offset); + outByte(0x1F4, offset >> 8); + outByte(0x1F5, offset >> 16); + outByte(0x1F6, (offset >> 24) | 0xE0); + outByte(0x1F7, 0x20); + + waitDisk(); + for (i = 0; i < SECTSIZE / 4; i ++) { + ((int *)dst)[i] = inLong(0x1F0); + } +} + +void initSeg() { + gdt[SEG_KCODE] = SEG(STA_X | STA_R, 0, 0xffffffff, DPL_KERN); + gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, DPL_KERN); + gdt[SEG_UCODE] = SEG(STA_X | STA_R, 0x400000, 0xffffffff, DPL_USER); + gdt[SEG_UDATA] = SEG(STA_W, 0x400000, 0xffffffff, DPL_USER); + gdt[SEG_TSS] = SEG16(STS_T32A, &tss, sizeof(TSS)-1, DPL_KERN); + gdt[SEG_TSS].s = 0; + + setGdt(gdt, sizeof(gdt)); + + /* + * 初始化TSS + */ + current_index = SEG_TSS + 1; + current_base = 0x800000; + + tss.ss0 = KSEL(SEG_KDATA); + tss.esp0 = 0x400000; + + asm volatile("ltr %%ax":: "a" (KSEL(SEG_TSS))); + + /*设置正确的段寄存器*/ + asm volatile("movw %%ax, %%es":: "a"(KSEL(SEG_KDATA))); //es + asm volatile("movw %%ax, %%ds":: "a"(KSEL(SEG_KDATA))); //ds + asm volatile("movw %%ax, %%ss":: "a"(KSEL(SEG_KDATA))); //ss + + lLdt(0); + +} + +void enterUserSpace(uint32_t entry) { + /* + * Before enter user space + * you should set the right segment registers here + * and use 'iret' to jump to ring3 + */ + uint32_t eflages = 0x00000002; + + asm volatile("movw %%ax, %%es":: "a"(USEL(SEG_UDATA))); //es + asm volatile("movw %%ax, %%ds":: "a"(USEL(SEG_UDATA))); //ds + + asm volatile("pushw %0":: "i"(USEL(SEG_UDATA))); //ss + asm volatile("pushl %0" :: "i"(128<<10)); //esp + + //iret will pop eip, cs, eflages + asm volatile("pushl %0" : : "m"(eflages)); //eflages + asm volatile("pushl %0":: "i"(USEL(SEG_UCODE))); //cs + asm volatile("pushl %0" : : "m"(entry)); //eip + + asm volatile("iret"); +} + + +uint32_t loadUMain() { + + /*加载用户程序至内存*/ + ELFHeader *elf; + ProgramHeader *ph = NULL; + char *p; + + uint8_t buf[BUFSIZE]; + int i; + for(i=0; i < NUM; i++) + readSect((void *)(buf+i*SECTSIZE), 201+i); + + elf = (void *)buf; + const uint32_t elf_magic = 0x464c457f; + uint32_t *p_magic = (void *)buf; + assert(*p_magic == elf_magic); + + for(i=0; i < elf->phnum; i++){ + ph = (ProgramHeader *)(buf + elf->phoff + elf->phentsize*i); + if(ph->type == PT_LOAD){ + p = (char *)ph->vaddr+0x400000; + memcpy(p, buf+ph->off, ph->filesz); + memset((void *)(p+ph->filesz), 0, ph->memsz-ph->filesz); + } + } + assert(elf->entry == 0x200000); + return elf->entry; +} + + + + diff --git a/lab4/kernel/kernel/pv.c b/lab4/kernel/kernel/pv.c new file mode 100644 index 0000000..6d76018 --- /dev/null +++ b/lab4/kernel/kernel/pv.c @@ -0,0 +1,131 @@ +#include "x86.h" + +struct ProcessTable* add_to_queue(struct ProcessTable * list, struct ProcessTable *m); +struct ProcessTable* del_to_queue(struct ProcessTable * list, struct ProcessTable *m); + +void add_to_pcb(PCB *p, int n) +{ + if(p != NULL){ + sem[n].next = -1; + if(p->sem_list < 0){ + p->sem_list = n; + } + else { + int prev = p->sem_list;; + while(sem[prev].next >= 0){ + prev = sem[prev].next; + } + sem[prev].next = n; + } + } +} +void del_to_pcb(PCB *p, int n) +{ + if(p != NULL){ + if(p->sem_list < 0) return; + else if (p->sem_list == n) p->sem_list = -1; + int prev = p->sem_list; + while(sem[prev].next >= 0 && sem[prev].next != n){ + prev = sem[prev].next; + } + if(sem[prev].next == n){ + sem[prev].next = sem[n].next; + sem[n].next = -1; + } + } +} + +PCB *sleep(PCB *list) +{ + list = add_to_queue(list, current); + current->state = TASK_BLOCKED; + need_resched = 1; + + return list; +} + +PCB *wakeup(PCB *list) +{ + PCB *p = list; + list = del_to_queue(list, list); + p->state = TASK_RUNNABLE; + run_list = add_to_queue(run_list, p); + return list; +} + +void P(Semaphore *s) +{ + s->value --; + if(s->value < 0) + s->list = sleep(s->list); +} + +void V(Semaphore *s) +{ + s->value ++; + if(s->value <= 0) + s->list = wakeup(s->list); +} + + +void sem_creat(struct TrapFrame *tf) +{ + current->tf->eax = (uint32_t)(&sem); +} + +void sem_init(struct TrapFrame *tf) +{ + int num = next_sem % MAX_SEM_NUM;//(Semaphore *)(tf->ecx); + uint32_t value = (tf->edx); + Semaphore *s = &sem[num];//(Semaphore *)(tf->ecx); + next_sem ++; + s->state = SEM_USED; + s->linkCount = 1; + s->value = value; + LOG_NUM(s->value, 10); + *(uint32_t *)(GDT_BASE((current->tf->ds) >> 3) + tf->ecx) = num; + add_to_pcb(current, num); + if(s->value == value) + current->tf->eax = 0; + else current->tf->eax = -1; +} + +void sem_post(struct TrapFrame *tf) +{ + //Semaphore *s = (Semaphore *)(tf->ecx); + Semaphore *s = &sem[tf->ecx]; + V(s); + current->tf->eax = 0; +} + +void sem_wait(struct TrapFrame *tf) +{ + //Semaphore *s = (Semaphore *)(tf->ecx); + Semaphore *s = &sem[tf->ecx]; + P(s); + current->tf->eax = 0; +} + +void sem_destroy(struct TrapFrame *tf) +{ +// Semaphore *s = (Semaphore *)(tf->ecx); + Semaphore *s = &sem[tf->ecx]; + s->linkCount --; + del_to_pcb(current, tf->ecx); + if(s->linkCount == 0) s->state = SEM_VALID; + //del s + current->tf->eax = 0; +} + +void initSEM() +{ + int i; + for(i=0; i < MAX_SEM_NUM; i++){ + sem[i].value = 0; + sem[i].list = NULL; + sem[i].state = SEM_VALID; + sem[i].linkCount = 0; + sem[i].next = -1; + } + next_sem = 0; +} diff --git a/lab4/kernel/kernel/schedule.c b/lab4/kernel/kernel/schedule.c new file mode 100644 index 0000000..f7f24d9 --- /dev/null +++ b/lab4/kernel/kernel/schedule.c @@ -0,0 +1,36 @@ +#include "x86.h" + +struct TSS tss; + +struct ProcessTable* add_to_queue(struct ProcessTable * list, struct ProcessTable *m); +struct ProcessTable* del_to_queue(struct ProcessTable * list, struct ProcessTable *m); + +void schedule() +{ + disableInterrupt(); + if(need_resched == 0) return; + need_resched = 0; + + struct ProcessTable *next; + next = NULL; + if(current != NULL && current->state == TASK_RUNNING) { + need_resched = 1; + } + else if((current == NULL || current->state != TASK_RUNNING) && run_list){ + next = run_list; + run_list = del_to_queue(run_list, next); + } + else{ + next = NULL; + } + if(next != NULL){//swithch to next + tss.esp0 = (uint32_t)(next->stack+MAX_STACK_SIZE - sizeof(struct TrapFrame)); + + current = next; + current->state = TASK_RUNNING; + if(current->timeCount <= 0) current->timeCount = 10; + } + else current = NULL; + +} + diff --git a/lab4/kernel/kernel/serial.c b/lab4/kernel/kernel/serial.c new file mode 100644 index 0000000..39b17fa --- /dev/null +++ b/lab4/kernel/kernel/serial.c @@ -0,0 +1,24 @@ +#include "x86.h" +#include "device.h" + + + +void initSerial(void) { + outByte(SERIAL_PORT + 1, 0x00); + outByte(SERIAL_PORT + 3, 0x80); + outByte(SERIAL_PORT + 0, 0x01); + outByte(SERIAL_PORT + 1, 0x00); + outByte(SERIAL_PORT + 3, 0x03); + outByte(SERIAL_PORT + 2, 0xC7); + outByte(SERIAL_PORT + 4, 0x0B); +} + +static inline int serialIdle(void) { + return (inByte(SERIAL_PORT + 5) & 0x20) != 0; +} + +void putChar(char ch) { + while (serialIdle() != TRUE); + outByte(SERIAL_PORT, ch); +} + diff --git a/lab4/kernel/kernel/timer.c b/lab4/kernel/kernel/timer.c new file mode 100644 index 0000000..2ee4e71 --- /dev/null +++ b/lab4/kernel/kernel/timer.c @@ -0,0 +1,12 @@ +#include "x86.h" + +#define TIMER_PORT 0x40 +#define FREQ_8253 1193182 +#define HZ 100 + +void initTimer() { + int counter = FREQ_8253 / HZ; + outByte(TIMER_PORT + 3, 0x34); + outByte(TIMER_PORT + 0, counter % 256); + outByte(TIMER_PORT + 0, counter / 256); +} diff --git a/lab4/kernel/lib/abort.c b/lab4/kernel/lib/abort.c new file mode 100644 index 0000000..4c848bc --- /dev/null +++ b/lab4/kernel/lib/abort.c @@ -0,0 +1,42 @@ +#include "common.h" +#include "x86.h" +#include "device.h" + +static char *i2A(int a) { + static char buf[30]; + char *p = buf + sizeof(buf) - 1; + do { + *--p = '0' + a % 10; + } while (a /= 10); + return p; +} + +static void append(char **p, const char *str) { + while (*str) { + *((*p) ++) = *str ++; + } +} + +/* 将文件名和assert fail的行号显示在屏幕上 */ +#define BLUE_SCREEN_TEXT "Assertion failed: " +static void displayMessage(const char *file, int line) { + static char buf[256] = BLUE_SCREEN_TEXT; + char *p = buf + sizeof(BLUE_SCREEN_TEXT) - 1; + + append(&p, file); + append(&p, ":"); + append(&p, i2A(line)); + append(&p, "\n"); + + for (p = buf; *p; p ++) { + putChar(*p); + } +} + +int abort(const char *fname, int line) { + disableInterrupt(); + displayMessage(fname, line); + while (TRUE) { + waitForInterrupt(); + } +} diff --git a/lab4/kernel/main.c b/lab4/kernel/main.c new file mode 100644 index 0000000..110af9e --- /dev/null +++ b/lab4/kernel/main.c @@ -0,0 +1,30 @@ +#include "common.h" +#include "x86.h" +#include "device.h" + +void initTimer(); +void initPCB(); +void initSEM(); +struct ProcessTable* initUserProcess(uint32_t entry); +void EnterUserSpace(struct ProcessTable *p); + +void kEntry(void) { + + initSerial();// initialize serial port + initIdt(); // initialize idt + initIntr(); // iniialize 8259a + initSeg(); // initialize gdt, tss + initTimer(); + uint32_t entry = loadUMain(); // load user program, enter user space + initPCB(); + void initSEM(); + initUserProcess(entry); + enableInterrupt(); + + while(1){ + waitForInterrupt(); + } + + while(1); + assert(0); +} diff --git a/lab4/lib/lib.h b/lab4/lib/lib.h new file mode 100644 index 0000000..01da787 --- /dev/null +++ b/lab4/lib/lib.h @@ -0,0 +1,25 @@ +#ifndef __lib_h__ +#define __lib_h__ + +#include "types.h" + +//#define sem_t uint32_t +struct sem_t { + int value; + uint32_t pcb; +}; +typedef struct sem_t sem_t; + +void printf(const char *format,...); +int fork(); +int sleep(uint32_t time); +int exit(); + +sem_t *sem_creat(); +int sem_init(sem_t *sem, uint32_t value); +int sem_post(sem_t *sem); +int sem_wait(sem_t *sem); +int sem_destroy(sem_t *sem); + + +#endif diff --git a/lab4/lib/syscall.c b/lab4/lib/syscall.c new file mode 100644 index 0000000..93596cb --- /dev/null +++ b/lab4/lib/syscall.c @@ -0,0 +1,185 @@ +#include "lib.h" +#include "types.h" +//#include +/* + * io lib here + * 库函数写在这 + */ + +typedef char * va_list ; + +#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) -1) & ~(sizeof(int)-1)) +#define va_start(ap, v) (ap = (va_list)&v + _INTSIZEOF(v)) +#define va_arg(ap, type) (*(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type))) +#define va_end(ap) (ap = (va_list)0) + +//int vsprintf(char *buf, const char *fmt, va_list args); + +int32_t syscall(int num, uint32_t a1,uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5) +{ + int32_t ret = 0; + + /* 内嵌汇编 保存 num, a1, a2, a3, a4, a5 至通用寄存器*/ + /* num--system call number + ** + */ + + asm volatile("pushl %ebx;\ + pushl %esi;\ + pushl %edi"); + asm volatile("movl %0, %%eax" :: "m"(num)); + asm volatile("movl %0, %%ecx" :: "m"(a1)); + asm volatile("movl %0, %%edx" :: "m"(a2)); + asm volatile("movl %0, %%ebx" :: "m"(a3)); + asm volatile("movl %0, %%esi" :: "m"(a4)); + asm volatile("movl %0, %%edi" :: "m"(a5)); + + asm volatile("int $0x80"); + + asm volatile("movl %%eax, %0" :"=m"(ret) :); + asm volatile("popl %edi;\ + popl %esi;\ + popl %ebx"); + + return ret; +} + +void write (void *buf, int len) +{ + int num = 4; + uint32_t fd = 1; + uint32_t ptr = (uint32_t)buf; + uint32_t size = (uint32_t)len; + + syscall(num, ptr, size, fd, 0, 0); +} + + +int itoa(int k, char *str, int hex) +{ + int i, j, n, base, sign; + char buf[32]; + if((k < 0) && hex == 10) { + sign = -1; + k = -k; + } + else sign = 1; + unsigned num = (unsigned)k; + i = 0; base = hex; + do{ + n = num % base; + if(n >= 0 && n <= 9) buf[i++] = n + '0'; + else buf[i++] = n + 'a'-10; + } while((num = num/base) > 0); + if(sign < 0) buf[i++] = '-'; + for(j=0; j < i; j++) + str[j] = buf[i-j-1]; + return i; +} + + + +int vsnprintf(char *buf, const char *format, va_list args) +{ + char *str; + char *arg; + + for(str=buf; *format; ++format){ + if(*format != '%'){ + *(str++) = *format; + continue; + } + format ++; + switch(*format){ + case 'x': + str += itoa(va_arg(args, int), str, 16); + break; + case 'c': + *(str++) = (unsigned char )va_arg(args, int); + break; + case 's': + arg = va_arg(args, char *); + for(; *arg; arg++) + *(str++) = *arg; + break; + case 'd': + str += itoa(va_arg(args, int), str, 10); + break; + default: *(str++) = *format; + } + + + } + va_end(args); + + return (str-buf); +} + + + +void printf(const char *format,...){ + static char buf[256]; + va_list args; + va_start(args, format); + int len = vsnprintf(buf, format, args); + write(buf, len); +} + + + +int fork() +{ + int num = 2; + int ret = syscall(num, 0, 0, 0, 0, 0); + return ret; +} + + +int sleep(uint32_t time) +{ + int num = 3; + int ret = syscall(num, time, 0, 0, 0, 0); + return ret; +} + +int exit() +{ + int num = 1; + int ret = syscall(num, 0, 0, 0, 0, 0); + return ret; +} + +sem_t *sem_creat() +{ + return (sem_t *)syscall(7, 0, 0, 0, 0, 0); +} + +int sem_init(sem_t *sem, uint32_t value) +{ + int num = 8; + int ret = syscall(num, (uint32_t)sem, value, 0, 0, 0); + return ret; +} + +int sem_post(sem_t *sem) +{ + int num = 9; + int ret = syscall(num, *(uint32_t *)sem, 0, 0, 0, 0); + return ret; +} + +int sem_wait(sem_t *sem) +{ + int num = 10; + int ret = syscall(num, *(uint32_t *)sem, 0, 0, 0, 0); + return ret; +} + +int sem_destroy(sem_t *sem) +{ + int num = 11; + int ret = syscall(num, *(uint32_t *)sem, 0, 0, 0, 0); + return ret; +} + diff --git a/lab4/lib/types.h b/lab4/lib/types.h new file mode 100644 index 0000000..deab367 --- /dev/null +++ b/lab4/lib/types.h @@ -0,0 +1,17 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned char boolean; + +typedef uint32_t size_t; +typedef int32_t pid_t; + + + +#endif diff --git a/lab4/utils/genBoot.pl b/lab4/utils/genBoot.pl new file mode 100644 index 0000000..5bc39bc --- /dev/null +++ b/lab4/utils/genBoot.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 1000); + +if($n > 510){ + print STDERR "ERROR: boot block too large: $n bytes (max 510)\n"; + exit 1; +} + +print STDERR "OK: boot block is $n bytes (max 510)\n"; + +$buf .= "\0" x (510-$n); +$buf .= "\x55\xAA"; + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/lab4/utils/genKernel.pl b/lab4/utils/genKernel.pl new file mode 100644 index 0000000..05ab188 --- /dev/null +++ b/lab4/utils/genKernel.pl @@ -0,0 +1,13 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 100000); + +print STDERR "OK: Kernel is $n bytes - Extended to 200 sectors\n"; + +$buf .= "\0" x (102400-$n); + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG;