实现多进程
This commit is contained in:
commit
62575faf43
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.vscode/
|
||||||
|
|
||||||
|
i686_elf_tools/
|
||||||
|
|
||||||
|
cmake-build-debug/
|
||||||
|
|
||||||
|
isodir/
|
33
boot/boot.asm
Normal file
33
boot/boot.asm
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
.set ALIGN, 1<<0
|
||||||
|
.set MEMINFO, 1<<1
|
||||||
|
.set FLAGS, ALIGN | MEMINFO
|
||||||
|
.set MAGIC, 0x1BADB002
|
||||||
|
.set CHECKSUM, -(MAGIC + FLAGS)
|
||||||
|
|
||||||
|
.section .multiboot
|
||||||
|
.align 4
|
||||||
|
.long MAGIC
|
||||||
|
.long FLAGS
|
||||||
|
.long CHECKSUM
|
||||||
|
|
||||||
|
.section .bss
|
||||||
|
.align 16
|
||||||
|
stack_bottom:
|
||||||
|
.skip 16384 # 16 KiB
|
||||||
|
stack_top:
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
.global _start
|
||||||
|
.type _start, @function
|
||||||
|
_start:
|
||||||
|
|
||||||
|
mov $stack_top, %esp
|
||||||
|
|
||||||
|
call kernel_main
|
||||||
|
|
||||||
|
cli
|
||||||
|
1: hlt
|
||||||
|
jmp 1b
|
||||||
|
|
||||||
|
.size _start, . - _start
|
128
boot/interrupt.asm
Normal file
128
boot/interrupt.asm
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
%macro ISR_NOERRCODE 1 ; nasm宏:定义ISR_NOERRCODE,接收一个参数
|
||||||
|
[global isr%1] ; %1代表第一个参数
|
||||||
|
isr%1:
|
||||||
|
cli
|
||||||
|
push byte 0
|
||||||
|
push %1
|
||||||
|
jmp isr_common_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro ISR_ERRCODE 1
|
||||||
|
[global isr%1]
|
||||||
|
isr%1:
|
||||||
|
cli
|
||||||
|
push %1
|
||||||
|
jmp isr_common_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
ISR_NOERRCODE 0
|
||||||
|
ISR_NOERRCODE 1
|
||||||
|
ISR_NOERRCODE 2
|
||||||
|
ISR_NOERRCODE 3
|
||||||
|
ISR_NOERRCODE 4
|
||||||
|
ISR_NOERRCODE 5
|
||||||
|
ISR_NOERRCODE 6
|
||||||
|
ISR_NOERRCODE 7
|
||||||
|
ISR_ERRCODE 8
|
||||||
|
ISR_NOERRCODE 9
|
||||||
|
ISR_ERRCODE 10
|
||||||
|
ISR_ERRCODE 11
|
||||||
|
ISR_ERRCODE 12
|
||||||
|
ISR_ERRCODE 13
|
||||||
|
ISR_ERRCODE 14
|
||||||
|
ISR_NOERRCODE 15
|
||||||
|
ISR_NOERRCODE 16
|
||||||
|
ISR_ERRCODE 17
|
||||||
|
ISR_NOERRCODE 18
|
||||||
|
ISR_NOERRCODE 19
|
||||||
|
ISR_NOERRCODE 20
|
||||||
|
ISR_ERRCODE 21
|
||||||
|
ISR_NOERRCODE 22
|
||||||
|
ISR_NOERRCODE 23
|
||||||
|
ISR_NOERRCODE 24
|
||||||
|
ISR_NOERRCODE 25
|
||||||
|
ISR_NOERRCODE 26
|
||||||
|
ISR_NOERRCODE 27
|
||||||
|
ISR_NOERRCODE 28
|
||||||
|
ISR_NOERRCODE 29
|
||||||
|
ISR_NOERRCODE 30
|
||||||
|
ISR_NOERRCODE 31
|
||||||
|
|
||||||
|
[extern isr_handler] ; 将会在isr.c中被定义
|
||||||
|
|
||||||
|
; 通用中断处理程序
|
||||||
|
isr_common_stub:
|
||||||
|
pusha ; 存储所有寄存器
|
||||||
|
|
||||||
|
mov ax, ds
|
||||||
|
push eax ; 存储ds
|
||||||
|
|
||||||
|
mov ax, 0x10 ; 将内核数据段赋值给各段
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
call isr_handler ; 调用C语言处理函数
|
||||||
|
pop eax ; 恢复各段
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
popa ; 弹出所有寄存器
|
||||||
|
|
||||||
|
add esp, 8 ; 弹出错误码和中断ID
|
||||||
|
iret ; 从中断返回
|
||||||
|
|
||||||
|
%macro IRQ 2
|
||||||
|
global irq%1
|
||||||
|
irq%1:
|
||||||
|
cli
|
||||||
|
push byte 0
|
||||||
|
push %2
|
||||||
|
jmp irq_common_stub
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
IRQ 0, 32
|
||||||
|
IRQ 1, 33
|
||||||
|
IRQ 2, 34
|
||||||
|
IRQ 3, 35
|
||||||
|
IRQ 4, 36
|
||||||
|
IRQ 5, 37
|
||||||
|
IRQ 6, 38
|
||||||
|
IRQ 7, 39
|
||||||
|
IRQ 8, 40
|
||||||
|
IRQ 9, 41
|
||||||
|
IRQ 10, 42
|
||||||
|
IRQ 11, 43
|
||||||
|
IRQ 12, 44
|
||||||
|
IRQ 13, 45
|
||||||
|
IRQ 14, 46
|
||||||
|
IRQ 15, 47
|
||||||
|
|
||||||
|
[extern irq_handler]
|
||||||
|
; 通用中断处理程序
|
||||||
|
irq_common_stub:
|
||||||
|
pusha ; 存储所有寄存器
|
||||||
|
|
||||||
|
mov ax, ds
|
||||||
|
push eax ; 存储ds
|
||||||
|
|
||||||
|
mov ax, 0x10 ; 将内核数据段赋值给各段
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
call irq_handler ; 调用C语言处理函数
|
||||||
|
|
||||||
|
pop eax ; 恢复各段
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
popa ; 弹出所有寄存器
|
||||||
|
|
||||||
|
add esp, 8 ; 弹出错误码和中断ID
|
||||||
|
iret ; 从中断返回
|
142
boot/io.asm
Normal file
142
boot/io.asm
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
section .data
|
||||||
|
|
||||||
|
global io_hlt, io_cli, io_sti, io_stihlt
|
||||||
|
global io_in8, io_in16, io_in32
|
||||||
|
global io_out8, io_out16, io_out32
|
||||||
|
global io_load_eflags, io_store_eflags
|
||||||
|
global load_gdtr, load_idtr
|
||||||
|
global tss_flush, gdt_flush, switch_to
|
||||||
|
|
||||||
|
section .text
|
||||||
|
|
||||||
|
switch_to:
|
||||||
|
mov eax, [esp+4]
|
||||||
|
|
||||||
|
mov [eax+0], esp
|
||||||
|
mov [eax+4], ebp
|
||||||
|
mov [eax+8], ebx
|
||||||
|
mov [eax+12], esi
|
||||||
|
mov [eax+16], edi
|
||||||
|
pushf
|
||||||
|
pop ecx
|
||||||
|
mov [eax+20], ecx
|
||||||
|
|
||||||
|
mov eax, [esp+8]
|
||||||
|
|
||||||
|
mov esp, [eax+0]
|
||||||
|
mov ebp, [eax+4]
|
||||||
|
mov ebx, [eax+8]
|
||||||
|
mov esi, [eax+12]
|
||||||
|
mov edi, [eax+16]
|
||||||
|
mov eax, [eax+20]
|
||||||
|
push eax
|
||||||
|
popf
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
[global read_port]
|
||||||
|
|
||||||
|
read_port:
|
||||||
|
mov edx, [esp + 4]
|
||||||
|
in al, dx
|
||||||
|
ret
|
||||||
|
|
||||||
|
[global idt_flush]
|
||||||
|
|
||||||
|
idt_flush: ; void idt_flush(uint32_t);
|
||||||
|
mov eax, [esp + 4]
|
||||||
|
lidt [eax]
|
||||||
|
ret
|
||||||
|
|
||||||
|
[global gdt_flush]
|
||||||
|
|
||||||
|
gdt_flush: ; void gdt_flush(uint32_t gdtr);
|
||||||
|
mov eax, [esp + 4] ; [esp+4]按规定是第一个参数,即gdtr
|
||||||
|
lgdt [eax] ; 加载新gdt指针,传入的是地址
|
||||||
|
|
||||||
|
mov ax, 0x10 ; 新数据段
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
mov fs, ax
|
||||||
|
mov gs, ax
|
||||||
|
mov ss, ax ; 各数据段全部划给这一数据段
|
||||||
|
jmp 0x08:.flush ; cs没法mov,只能用farjmp/farcall,这里用farjmp刷新cs
|
||||||
|
.flush:
|
||||||
|
ret ; 刷新完毕,返回
|
||||||
|
|
||||||
|
tss_flush:
|
||||||
|
mov ax, 0x2B
|
||||||
|
ltr ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
io_hlt: ; void io_hlt(void);
|
||||||
|
HLT
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_cli: ; void io_cli(void);
|
||||||
|
CLI
|
||||||
|
RET
|
||||||
|
io_sti: ; void io_sti(void);
|
||||||
|
STI
|
||||||
|
RET
|
||||||
|
io_stihlt: ; void io_stihlt(void);
|
||||||
|
STI
|
||||||
|
HLT
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_in8: ; int io_in8(int port);
|
||||||
|
MOV EDX,[ESP+4] ; port
|
||||||
|
MOV EAX,0
|
||||||
|
IN AL,DX
|
||||||
|
RET
|
||||||
|
io_in16: ; int io_in16(int port);
|
||||||
|
MOV EDX,[ESP+4] ; port
|
||||||
|
MOV EAX,0
|
||||||
|
IN AX,DX
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_in32: ; int io_in32(int port);
|
||||||
|
MOV EDX,[ESP+4] ; port
|
||||||
|
IN EAX,DX
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_out8: ; void io_out8(int port, int data);
|
||||||
|
MOV EDX,[ESP+4] ; port
|
||||||
|
MOV AL,[ESP+8] ; data
|
||||||
|
OUT DX,AL
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_out16: ; void io_out16(int port, int data);
|
||||||
|
MOV EDX,[ESP+4] ; port
|
||||||
|
MOV EAX,[ESP+8] ; data
|
||||||
|
OUT DX,AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_out32: ; void io_out32(int port, int data);
|
||||||
|
MOV EDX,[ESP+4] ; port
|
||||||
|
MOV EAX,[ESP+8] ; data
|
||||||
|
OUT DX,EAX
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_load_eflags: ; int io_load_eflags(void);
|
||||||
|
PUSHFD ; PUSH EFLAGS
|
||||||
|
POP EAX
|
||||||
|
RET
|
||||||
|
|
||||||
|
io_store_eflags: ; void io_store_eflags(int eflags);
|
||||||
|
MOV EAX,[ESP+4]
|
||||||
|
PUSH EAX
|
||||||
|
POPFD ; POP EFLAGS
|
||||||
|
RET
|
||||||
|
|
||||||
|
load_gdtr: ; void load_gdtr(int limit, int addr);
|
||||||
|
MOV AX,[ESP+4] ; limit
|
||||||
|
MOV [ESP+6],AX
|
||||||
|
LGDT [ESP+6]
|
||||||
|
RET
|
||||||
|
|
||||||
|
load_idtr: ; void load_idtr(int limit, int addr);
|
||||||
|
MOV AX,[ESP+4] ; limit
|
||||||
|
MOV [ESP+6],AX
|
||||||
|
LIDT [ESP+6]
|
||||||
|
RET
|
104
build.py
Normal file
104
build.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
gcc = '/i686_elf_tools/bin/i686-elf-gcc.exe -I include/ -std=gnu99 -ffreestanding -O2 -c -Wincompatible-pointer-types'
|
||||||
|
asm = '/i686_elf_tools/bin/i686-elf-as.exe'
|
||||||
|
nasm = "nasm -f elf32"
|
||||||
|
ld = '/i686_elf_tools/bin/i686-elf-ld.exe'
|
||||||
|
|
||||||
|
cd = os.getcwd() # 获取当前执行目录 'D:\CrashPowerDOS-main\'
|
||||||
|
|
||||||
|
out = "target"
|
||||||
|
|
||||||
|
|
||||||
|
def clean():
|
||||||
|
print("Clean target flolder")
|
||||||
|
for file in os.listdir(cd + "\\target"): # 遍历指定文件夹下所有文件
|
||||||
|
os.remove(cd + "\\target\\" + file)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def build_boot(): # 构建引导程序
|
||||||
|
print("Building boot source code...")
|
||||||
|
status = True
|
||||||
|
for file in os.listdir(cd + '\\boot'):
|
||||||
|
if status and file == 'boot.asm':
|
||||||
|
cmd = cd + asm + " " + cd + "\\boot\\" + file + " -o " + cd + "\\target\\" + file.split(".")[0] + ".o"
|
||||||
|
status = False
|
||||||
|
else:
|
||||||
|
cmd = nasm + " " + cd + "\\boot\\" + file + " -o " + cd + "\\target\\" + file.split(".")[0] + ".o"
|
||||||
|
e = os.system(cmd) # os.system 执行命令 e为返回值(非0即不正常退出,可做判断终止构建流程)
|
||||||
|
if e != 0:
|
||||||
|
return -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def build_driver(): # 构建内置驱动程序
|
||||||
|
print("Building driver source code...")
|
||||||
|
for file in os.listdir(cd + '\\driver'):
|
||||||
|
cmd = cd + gcc + " " + "driver\\" + file + " -o " + "target\\" + file.split(".")[0] + ".o"
|
||||||
|
e = os.system(cmd)
|
||||||
|
if e != 0:
|
||||||
|
return -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def build_kernel(): # 构建内核本体
|
||||||
|
print("Building kernel source code...")
|
||||||
|
for file in os.listdir(cd + '\\kernel'):
|
||||||
|
cmd = cd + gcc + " " + "kernel\\" + file + " -o " + "target\\" + file.split(".")[0] + ".o"
|
||||||
|
e = os.system(cmd)
|
||||||
|
if e != 0:
|
||||||
|
return -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def build_data(): # 构建数据结构实现
|
||||||
|
print("Building data source code...")
|
||||||
|
for file in os.listdir(cd + '\\data'):
|
||||||
|
cmd = cd + gcc + " " + "data\\" + file + " -o " + "target\\" + file.split(".")[0] + ".o"
|
||||||
|
e = os.system(cmd)
|
||||||
|
if e != 0:
|
||||||
|
return -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def build_sysapp(): # 构建内置系统应用
|
||||||
|
print("Building sysapp source code...")
|
||||||
|
for file in os.listdir(cd + '\\sysapp'):
|
||||||
|
cmd = cd + gcc + " " + "sysapp\\" + file + " -o " + "target\\" + file.split(".")[0] + ".o"
|
||||||
|
e = os.system(cmd)
|
||||||
|
if e != 0:
|
||||||
|
return -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def linker(): # 交叉编译链接
|
||||||
|
print("Linking object files...")
|
||||||
|
source_file = ""
|
||||||
|
for file in os.listdir(cd + '\\target'):
|
||||||
|
source_file = source_file + " target\\" + file
|
||||||
|
return os.system(
|
||||||
|
cd + "/i686_elf_tools/bin/i686-elf-gcc.exe -T linker.ld -o isodir\\sys\\kernel.elf -ffreestanding -O2 -nostdlib " + source_file + " -lgcc")
|
||||||
|
|
||||||
|
|
||||||
|
clean()
|
||||||
|
a = build_boot()
|
||||||
|
if a != 0:
|
||||||
|
exit(-1)
|
||||||
|
a = build_driver()
|
||||||
|
if a != 0:
|
||||||
|
exit(-1)
|
||||||
|
a = build_kernel()
|
||||||
|
if a != 0:
|
||||||
|
exit(-1)
|
||||||
|
a = build_data()
|
||||||
|
if a != 0:
|
||||||
|
exit(-1)
|
||||||
|
a = build_sysapp()
|
||||||
|
if a != 0:
|
||||||
|
exit(-1)
|
||||||
|
a = linker()
|
||||||
|
if a != 0:
|
||||||
|
exit(-1)
|
||||||
|
print("Launching i386 vm...")
|
||||||
|
os.system("qemu-system-i386 -kernel isodir\\sys\\kernel.elf -drive format=qcow2,file=cpos.qcow2")
|
BIN
cpos.qcow2
Normal file
BIN
cpos.qcow2
Normal file
Binary file not shown.
58
data/queue.c
Normal file
58
data/queue.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "../include/queue.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
Queue *create_queue() {
|
||||||
|
Queue *queue = (Queue *) kmalloc(sizeof(Queue));
|
||||||
|
queue->phead = NULL;
|
||||||
|
queue->ptail = NULL;
|
||||||
|
queue->size = 0;
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_queue(Queue *queue) {
|
||||||
|
QNode *cur = queue->phead;
|
||||||
|
while (cur) {
|
||||||
|
QNode *next = cur->next;
|
||||||
|
kfree(cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
queue->phead = queue->ptail = NULL;
|
||||||
|
kfree(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_push(Queue *pq, char x) {
|
||||||
|
QNode *newnode = (QNode *) kmalloc(sizeof(QNode));//为新节点申请内存空间
|
||||||
|
if (newnode == NULL) {
|
||||||
|
printf("OUT_OF_MEMORY: The kernel memory out of.");
|
||||||
|
io_cli();
|
||||||
|
for (;;)io_hlt();
|
||||||
|
}
|
||||||
|
newnode->data = x; //新节点储存数据
|
||||||
|
newnode->next = NULL;//新节点的下一个指向NULL,即新节点作为队尾
|
||||||
|
if (pq->phead == NULL)//将新节点入队
|
||||||
|
{
|
||||||
|
pq->phead = pq->ptail = newnode;
|
||||||
|
pq->phead->next = newnode;
|
||||||
|
} else {
|
||||||
|
pq->ptail->next = newnode;
|
||||||
|
pq->ptail = newnode;
|
||||||
|
}
|
||||||
|
pq->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char queue_pop(Queue *pq) {
|
||||||
|
if (pq->size == 0)return NULL;
|
||||||
|
QNode *next = pq->phead->next;
|
||||||
|
kfree(pq->phead);
|
||||||
|
pq->phead = next;
|
||||||
|
if (pq->phead == NULL) {
|
||||||
|
pq->ptail = NULL;
|
||||||
|
}
|
||||||
|
pq->size -= 1;
|
||||||
|
return next->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
113
driver/cmos.c
Normal file
113
driver/cmos.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include "../include/cmos.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/common.h"
|
||||||
|
|
||||||
|
static void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
|
||||||
|
*eax = op;
|
||||||
|
*ecx = 0;
|
||||||
|
asm volatile("cpuid"
|
||||||
|
: "=a" (*eax), //输出参数
|
||||||
|
"=b" (*ebx),
|
||||||
|
"=c" (*ecx),
|
||||||
|
"=d" (*edx)
|
||||||
|
: "0" (*eax), "2" (*ecx) //输入参数
|
||||||
|
: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_vendor_name(cpu_t *c) {
|
||||||
|
int cpuid_level;
|
||||||
|
char x86_vendor_id[16] = {0};
|
||||||
|
cpuid(0x00000000, (unsigned int *) &cpuid_level,
|
||||||
|
(unsigned int *) &x86_vendor_id[0],
|
||||||
|
(unsigned int *) &x86_vendor_id[8],
|
||||||
|
(unsigned int *) &x86_vendor_id[4]);
|
||||||
|
c->vendor = x86_vendor_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_model_name(cpu_t *c) {
|
||||||
|
unsigned int *v = (unsigned int *) c->model_name;
|
||||||
|
cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
|
||||||
|
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
|
||||||
|
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
|
||||||
|
c->model_name[48] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_cpu_address_sizes(cpu_t *c) {
|
||||||
|
unsigned int eax, ebx, ecx, edx;
|
||||||
|
cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
c->virt_bits = (eax >> 8) & 0xff;
|
||||||
|
c->phys_bits = eax & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_cpu_id() {
|
||||||
|
cpu_t *c = (cpu_t *) kmalloc(sizeof(cpu_t));
|
||||||
|
get_vendor_name(c);
|
||||||
|
get_model_name(c);
|
||||||
|
get_cpu_address_sizes(c);
|
||||||
|
printf("CPU Vendor: %s\n", c->vendor);
|
||||||
|
printf("CPU Name: %s\n", c->model_name);
|
||||||
|
printf("CPU Cache: %d\n",c->phys_bits);
|
||||||
|
printf("CPU Virtual Address: 0x%x\n",c->virt_bits);
|
||||||
|
kfree(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_cmos(uint8_t p) {
|
||||||
|
uint8_t data;
|
||||||
|
outb(CMOS_INDEX, p);
|
||||||
|
data = inb(CMOS_DATA);
|
||||||
|
outb(CMOS_INDEX, 0x80);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_hour() {
|
||||||
|
return bcd2hex(read_cmos(CMOS_CUR_HOUR));
|
||||||
|
}
|
||||||
|
|
||||||
|
;static uint32_t get_min() {
|
||||||
|
return bcd2hex(read_cmos(CMOS_CUR_MIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_sec() {
|
||||||
|
return bcd2hex(read_cmos(CMOS_CUR_SEC));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_day_of_month() {
|
||||||
|
return bcd2hex(read_cmos(CMOS_MON_DAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_day_of_week() {
|
||||||
|
return bcd2hex(read_cmos(CMOS_WEEK_DAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_mon() {
|
||||||
|
return bcd2hex(read_cmos(CMOS_CUR_MON));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t get_year() {
|
||||||
|
return (bcd2hex(read_cmos(CMOS_CUR_CEN)) * 100) + bcd2hex(read_cmos(CMOS_CUR_YEAR)) + 1980;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_leap_year(int year) {
|
||||||
|
if (year % 4 != 0) return 0;
|
||||||
|
if (year % 400 == 0) return 1;
|
||||||
|
return year % 100 != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_date_time() {
|
||||||
|
char *s = (char *) kmalloc(40);
|
||||||
|
int year = get_year(), month = get_mon(), day = get_day_of_month();
|
||||||
|
int hour = get_hour(), min = get_min(), sec = get_sec();
|
||||||
|
int day_of_months[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
if (is_leap_year(year)) day_of_months[2]++;
|
||||||
|
#ifdef NEED_UTC_8
|
||||||
|
hour += 8;
|
||||||
|
if (hour >= 24) hour -= 24, day++;
|
||||||
|
if (day > day_of_months[month]) day = 1, month++;
|
||||||
|
if (month > 12) month = 1, year++;
|
||||||
|
#endif
|
||||||
|
sprintf(s, "%d/%d/%d %d:%d:%d", year, month, day, hour, min, sec);
|
||||||
|
return s;
|
||||||
|
}
|
60
driver/disk.c
Normal file
60
driver/disk.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "../include/disk.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
void wait_disk_ready() {
|
||||||
|
while (1) {
|
||||||
|
int data = io_in8(0x1f7);
|
||||||
|
if ((data & 0x88) == 0x08) // 第3位为1表示硬盘控制器已准备好数据传输,第7位为1表示硬盘忙。
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void select_sector(int lba) {
|
||||||
|
io_out8(0x1f2, 1);
|
||||||
|
io_out8(0x1f3, lba);
|
||||||
|
io_out8(0x1f4, lba >> 8);
|
||||||
|
io_out8(0x1f5, lba >> 16);
|
||||||
|
io_out8(0x1f6, (((lba >> 24) & 0x0f) | 0xe0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_disk_one_sector(int lba, unsigned int memory_addrress) {
|
||||||
|
while (io_in8(0x1f7) & 0x80);
|
||||||
|
select_sector(lba);
|
||||||
|
io_out8(0x1f7, 0x20);
|
||||||
|
wait_disk_ready();
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
short data = (short) io_in16(0x1f0);
|
||||||
|
*((short *) memory_addrress) = data;
|
||||||
|
memory_addrress += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_disk_one_sertor(int lba, unsigned int memory_addrress) {
|
||||||
|
while (io_in8(0x1f7) & 0x80);
|
||||||
|
select_sector(lba);
|
||||||
|
io_out8(0x1f7, 0x30);
|
||||||
|
wait_disk_ready();
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
short data = *((short *) memory_addrress);
|
||||||
|
io_out16(0x1f0, data);
|
||||||
|
memory_addrress += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_disk(int lba, int sector_count, unsigned int memory_addrress) {
|
||||||
|
for (int i = 0; i < sector_count; i++) {
|
||||||
|
read_disk_one_sector(lba, memory_addrress);
|
||||||
|
lba++;
|
||||||
|
memory_addrress += 512;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_disk(int lba, int sector_count, unsigned int memory_addrress) {
|
||||||
|
for (int i = 0; i < sector_count; i++) {
|
||||||
|
write_disk_one_sertor(lba, memory_addrress);
|
||||||
|
lba++;
|
||||||
|
memory_addrress += 512;
|
||||||
|
}
|
||||||
|
}
|
121
driver/keyboard.c
Normal file
121
driver/keyboard.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include "../include/keyboard.h"
|
||||||
|
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/queue.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
static KEY_STATUS *key_status;
|
||||||
|
Queue *key_char_queue;
|
||||||
|
|
||||||
|
unsigned char keyboard_map[128] =
|
||||||
|
{
|
||||||
|
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
||||||
|
'9', '0', '-', '=', '\b', /* Backspace */
|
||||||
|
'\t', /* Tab */
|
||||||
|
'q', 'w', 'e', 'r', /* 19 */
|
||||||
|
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
|
||||||
|
0, /* 29 - Control */
|
||||||
|
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
|
||||||
|
'\'', '`', -1, /* Left shift */
|
||||||
|
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
|
||||||
|
'm', ',', '.', '/', -1, /* Right shift */
|
||||||
|
'*',
|
||||||
|
0, /* Alt */
|
||||||
|
' ', /* Space bar */
|
||||||
|
0, /* Caps lock */
|
||||||
|
0, /* 59 - F1 key ... > */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, /* < ... F10 */
|
||||||
|
0, /* 69 - Num lock*/
|
||||||
|
0, /* Scroll Lock */
|
||||||
|
0, /* Home key */
|
||||||
|
0, /* Up Arrow */
|
||||||
|
0, /* Page Up */
|
||||||
|
'-',
|
||||||
|
0, /* Left Arrow */
|
||||||
|
0,
|
||||||
|
0, /* Right Arrow */
|
||||||
|
'+',
|
||||||
|
0, /* 79 - End key*/
|
||||||
|
0, /* Down Arrow */
|
||||||
|
0, /* Page Down */
|
||||||
|
0, /* Insert Key */
|
||||||
|
0, /* Delete Key */
|
||||||
|
0, 0, 0,
|
||||||
|
0, /* F11 Key */
|
||||||
|
0, /* F12 Key */
|
||||||
|
0, /* All other keys are undefined */
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char shift_keyboard_map[128] =
|
||||||
|
{
|
||||||
|
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */
|
||||||
|
'(', ')', '_', '+', '\b', /* Backspace */
|
||||||
|
'\t', /* Tab */
|
||||||
|
'Q', 'W', 'E', 'R', /* 19 */
|
||||||
|
'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */
|
||||||
|
0, /* 29 - Control */
|
||||||
|
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */
|
||||||
|
'"', '~', -1, /* Left shift */
|
||||||
|
'|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */
|
||||||
|
'M', '<', '>', '?', -1, /* Right shift */
|
||||||
|
'*',
|
||||||
|
0, /* Alt */
|
||||||
|
' ', /* Space bar */
|
||||||
|
0, /* Caps lock */
|
||||||
|
0, /* 59 - F1 key ... > */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, /* < ... F10 */
|
||||||
|
0, /* 69 - Num lock*/
|
||||||
|
0, /* Scroll Lock */
|
||||||
|
0, /* Home key */
|
||||||
|
0, /* Up Arrow */
|
||||||
|
0, /* Page Up */
|
||||||
|
'-',
|
||||||
|
0, /* Left Arrow */
|
||||||
|
0,
|
||||||
|
0, /* Right Arrow */
|
||||||
|
'+',
|
||||||
|
0, /* 79 - End key*/
|
||||||
|
0, /* Down Arrow */
|
||||||
|
0, /* Page Down */
|
||||||
|
0, /* Insert Key */
|
||||||
|
0, /* Delete Key */
|
||||||
|
0, 0, 0,
|
||||||
|
0, /* F11 Key */
|
||||||
|
0, /* F12 Key */
|
||||||
|
0, /* All other keys are undefined */
|
||||||
|
};
|
||||||
|
|
||||||
|
void init_keyboard(){
|
||||||
|
key_status = (KEY_STATUS*) alloc(sizeof(KEY_STATUS));
|
||||||
|
key_status->is_shift = 0;
|
||||||
|
|
||||||
|
key_char_queue = create_queue();
|
||||||
|
register_interrupt_handler(0x21,handle_keyboard_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle_keyboard_input(){
|
||||||
|
unsigned char status = read_port(KEYBOARD_STATUS_PORT);
|
||||||
|
uint32_t key = read_port(KEYBOARD_DATA_PORT);
|
||||||
|
int release = key & 0xb10000000;
|
||||||
|
char c = key_status->is_shift ? shift_keyboard_map[(unsigned char )key] : keyboard_map[(unsigned char )key];
|
||||||
|
|
||||||
|
if(!release) {
|
||||||
|
if(c == -1) {
|
||||||
|
key_status->is_shift = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == 0) return 0;
|
||||||
|
|
||||||
|
queue_push(key_char_queue,(char)c);
|
||||||
|
} else {
|
||||||
|
if(c == -1){
|
||||||
|
key_status->is_shift = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
135
driver/vga.c
Normal file
135
driver/vga.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/common.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
static const size_t VGA_WIDTH = 80;
|
||||||
|
static const size_t VGA_HEIGHT = 25;
|
||||||
|
|
||||||
|
size_t terminal_row;
|
||||||
|
size_t terminal_column;
|
||||||
|
uint8_t terminal_color;
|
||||||
|
uint16_t *terminal_buffer;
|
||||||
|
|
||||||
|
static uint16_t cursor_x = 0, cursor_y = 0; // 光标位置
|
||||||
|
|
||||||
|
static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
|
||||||
|
return fg | bg << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t vga_entry(unsigned char uc, uint8_t color) {
|
||||||
|
return (uint16_t) uc | (uint16_t) color << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scroll() {
|
||||||
|
uint8_t attributeByte = (0 << 4) | (15 & 0x0F);
|
||||||
|
uint16_t blank = 0x20 | (attributeByte << 8);
|
||||||
|
|
||||||
|
if (cursor_y >= 25) {
|
||||||
|
int i;
|
||||||
|
for (i = 0 * 80; i < 24 * 80; i++) terminal_buffer[i] = terminal_buffer[i + 80];
|
||||||
|
for (i = 24 * 80; i < 25 * 80; i++) terminal_buffer[i] = blank;
|
||||||
|
cursor_y = 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_install(void) {
|
||||||
|
terminal_row = 0;
|
||||||
|
terminal_column = 0;
|
||||||
|
terminal_color = vga_entry_color(VGA_COLOR_DARK_GREY, VGA_COLOR_BLACK);
|
||||||
|
terminal_buffer = (uint16_t *) 0xB8000;
|
||||||
|
//terminal_buffer = (uint16_t*) 0xA0000;
|
||||||
|
for (size_t y = 0; y < VGA_HEIGHT; y++) {
|
||||||
|
for (size_t x = 0; x < VGA_WIDTH; x++) {
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_clear() {
|
||||||
|
for (size_t y = 0; y < VGA_HEIGHT; y++) {
|
||||||
|
for (size_t x = 0; x < VGA_WIDTH; x++) {
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor_x = 0;
|
||||||
|
cursor_y = 0;
|
||||||
|
move_cursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_cursor() {
|
||||||
|
uint16_t cursorLocation = cursor_y * 80 + cursor_x;
|
||||||
|
outb(0x3D4, 14);
|
||||||
|
outb(0x3D5, cursorLocation >> 8);
|
||||||
|
outb(0x3D4, 15);
|
||||||
|
outb(0x3D5, cursorLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_setcolor(uint8_t color) {
|
||||||
|
terminal_color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_putentryat(char c, uint8_t color, size_t x, size_t y) {
|
||||||
|
const size_t index = y * VGA_WIDTH + x;
|
||||||
|
terminal_buffer[index] = vga_entry(c, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_putchar(char c) {
|
||||||
|
uint8_t backColor = 0, foreColor = 15;
|
||||||
|
uint8_t attributeByte = (backColor << 4) | (foreColor & 0x07); // 黑底白字
|
||||||
|
uint16_t attribute = attributeByte << 8;
|
||||||
|
uint16_t *location;
|
||||||
|
|
||||||
|
if (c == 0x08 && cursor_x) {
|
||||||
|
cursor_x--;
|
||||||
|
location = terminal_buffer + (cursor_y * 80 + cursor_x);
|
||||||
|
*location = ' ' | attribute;
|
||||||
|
} else if (c == 0x09) {
|
||||||
|
location = terminal_buffer + (cursor_y * 80 + cursor_x);
|
||||||
|
*location = ' ' | attribute;
|
||||||
|
cursor_x = (cursor_x + 8) & ~(8 - 1);
|
||||||
|
} else if (c == '\r') {
|
||||||
|
cursor_x = 0;
|
||||||
|
} else if (c == '\n') {
|
||||||
|
cursor_x = 0; // 光标回首
|
||||||
|
cursor_y++; // 下一行
|
||||||
|
} else if (c >= ' ' && c <= '~') {
|
||||||
|
location = terminal_buffer + (cursor_y * 80 + cursor_x);
|
||||||
|
*location = c | attribute;
|
||||||
|
cursor_x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor_x >= 80) {
|
||||||
|
cursor_x = 0;
|
||||||
|
cursor_y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll();
|
||||||
|
move_cursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_write_dec(uint32_t dec) {
|
||||||
|
int upper = dec / 10, rest = dec % 10;
|
||||||
|
if (upper) vga_write_dec(upper);
|
||||||
|
vga_putchar(rest + '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_write(const char *data, size_t size) {
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
vga_putchar(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vga_writestring(const char *data) {
|
||||||
|
vga_write(data, strlen(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void printf(const char *formet, ...) {
|
||||||
|
int len;
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, formet);
|
||||||
|
char *buf[1024] = {0};
|
||||||
|
len = vsprintf(buf, formet, ap);
|
||||||
|
vga_writestring(buf);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
33
include/cmos.h
Normal file
33
include/cmos.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef CRASHPOWEROS_CMOS_H
|
||||||
|
#define CRASHPOWEROS_CMOS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define NEED_UTC_8
|
||||||
|
|
||||||
|
#define CMOS_INDEX 0x70
|
||||||
|
#define CMOS_DATA 0x71
|
||||||
|
|
||||||
|
#define CMOS_CUR_SEC 0x0
|
||||||
|
#define CMOS_CUR_MIN 0x2
|
||||||
|
#define CMOS_CUR_HOUR 0x4
|
||||||
|
#define CMOS_WEEK_DAY 0x6
|
||||||
|
#define CMOS_MON_DAY 0x7
|
||||||
|
#define CMOS_CUR_MON 0x8
|
||||||
|
#define CMOS_CUR_YEAR 0x9
|
||||||
|
#define CMOS_CUR_CEN 0x32
|
||||||
|
|
||||||
|
#define bcd2hex(n) ((n >> 4) * 10) + (n & 0xf)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* vendor;
|
||||||
|
char model_name[64];
|
||||||
|
unsigned int virt_bits;
|
||||||
|
unsigned int phys_bits;
|
||||||
|
}cpu_t;
|
||||||
|
|
||||||
|
uint8_t read_cmos(uint8_t p);
|
||||||
|
char *get_date_time();
|
||||||
|
void print_cpu_id();
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_CMOS_H
|
30
include/common.h
Normal file
30
include/common.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef CRASHPOWEROS_COMMON_H
|
||||||
|
#define CRASHPOWEROS_COMMON_H
|
||||||
|
|
||||||
|
#define OS_NAME "CrashPowerDOS"
|
||||||
|
#define OS_VERSION "v0.2.0"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void assert(int b,char* message);
|
||||||
|
size_t strlen(const char* str);
|
||||||
|
int strcmp(const char *s1, const char *s2);
|
||||||
|
char *strcpy(char *dest, const char *src);
|
||||||
|
char* strcat(char *dest, const char*src);
|
||||||
|
void trim(char *s);
|
||||||
|
int isspace(int c);
|
||||||
|
int isdigit(int c);
|
||||||
|
int isalpha(int c);
|
||||||
|
int isupper(int c);
|
||||||
|
char *int32_to_str_dec(int32_t num, int flag, int width);
|
||||||
|
char *int64_to_str_dec(int64_t num, int flag, int width);
|
||||||
|
char *uint32_to_str_hex(uint32_t num, int flag, int width);
|
||||||
|
char *uint64_to_str_hex(uint64_t num, int flag, int width);
|
||||||
|
char *uint32_to_str_oct(uint32_t num, int flag, int width);
|
||||||
|
char *insert_str(char *buf, const char *str);
|
||||||
|
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||||
|
int sprintf(char *buf, const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_COMMON_H
|
129
include/description_table.h
Normal file
129
include/description_table.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#ifndef CRASHPOWEROS_DESCRIPTION_TABLE_H
|
||||||
|
#define CRASHPOWEROS_DESCRIPTION_TABLE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define GDT_LENGTH 6
|
||||||
|
|
||||||
|
typedef struct gdt_entry_t {
|
||||||
|
uint16_t limit_low; // 段基址 | 低16位置
|
||||||
|
uint16_t base_low; // 段基址 | 高16位置
|
||||||
|
uint8_t base_middle;
|
||||||
|
uint8_t access;
|
||||||
|
uint8_t granularity;
|
||||||
|
uint8_t base_high;
|
||||||
|
} __attribute__((packed)) gdt_entry_t;
|
||||||
|
|
||||||
|
typedef struct gdt_ptr_t {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed)) gdt_ptr_t;
|
||||||
|
|
||||||
|
#define DECLARE_ISR(i) extern void isr##i();
|
||||||
|
|
||||||
|
DECLARE_ISR(0)
|
||||||
|
DECLARE_ISR(1)
|
||||||
|
DECLARE_ISR(2)
|
||||||
|
DECLARE_ISR(3)
|
||||||
|
DECLARE_ISR(4)
|
||||||
|
DECLARE_ISR(5)
|
||||||
|
DECLARE_ISR(6)
|
||||||
|
DECLARE_ISR(7)
|
||||||
|
DECLARE_ISR(8)
|
||||||
|
DECLARE_ISR(9)
|
||||||
|
DECLARE_ISR(10)
|
||||||
|
DECLARE_ISR(11)
|
||||||
|
DECLARE_ISR(12)
|
||||||
|
DECLARE_ISR(13)
|
||||||
|
DECLARE_ISR(14)
|
||||||
|
DECLARE_ISR(15)
|
||||||
|
DECLARE_ISR(16)
|
||||||
|
DECLARE_ISR(17)
|
||||||
|
DECLARE_ISR(18)
|
||||||
|
DECLARE_ISR(19)
|
||||||
|
DECLARE_ISR(20)
|
||||||
|
DECLARE_ISR(21)
|
||||||
|
DECLARE_ISR(22)
|
||||||
|
DECLARE_ISR(23)
|
||||||
|
DECLARE_ISR(24)
|
||||||
|
DECLARE_ISR(25)
|
||||||
|
DECLARE_ISR(26)
|
||||||
|
DECLARE_ISR(27)
|
||||||
|
DECLARE_ISR(28)
|
||||||
|
DECLARE_ISR(29)
|
||||||
|
DECLARE_ISR(30)
|
||||||
|
DECLARE_ISR(31)
|
||||||
|
#undef DECLARE_ISR
|
||||||
|
#define DECLARE_IRQ(i) extern void irq##i();
|
||||||
|
DECLARE_IRQ(0)
|
||||||
|
DECLARE_IRQ(1)
|
||||||
|
DECLARE_IRQ(2)
|
||||||
|
DECLARE_IRQ(3)
|
||||||
|
DECLARE_IRQ(4)
|
||||||
|
DECLARE_IRQ(5)
|
||||||
|
DECLARE_IRQ(6)
|
||||||
|
DECLARE_IRQ(7)
|
||||||
|
DECLARE_IRQ(8)
|
||||||
|
DECLARE_IRQ(9)
|
||||||
|
DECLARE_IRQ(10)
|
||||||
|
DECLARE_IRQ(11)
|
||||||
|
DECLARE_IRQ(12)
|
||||||
|
DECLARE_IRQ(13)
|
||||||
|
DECLARE_IRQ(14)
|
||||||
|
DECLARE_IRQ(15)
|
||||||
|
#undef DECLARE_IRQ
|
||||||
|
|
||||||
|
struct idt_entry_struct {
|
||||||
|
uint16_t base_low;
|
||||||
|
uint16_t sel;
|
||||||
|
uint8_t always0;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t base_high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef struct idt_entry_struct idt_entry_t;
|
||||||
|
|
||||||
|
// IDTR
|
||||||
|
struct idt_ptr_struct {
|
||||||
|
uint16_t limit;
|
||||||
|
uint32_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef struct idt_ptr_struct idt_ptr_t;
|
||||||
|
|
||||||
|
typedef struct tss_table {
|
||||||
|
uint32_t prev_tss;
|
||||||
|
uint32_t esp0;
|
||||||
|
uint32_t ss0;
|
||||||
|
uint32_t esp1;
|
||||||
|
uint32_t ss1;
|
||||||
|
uint32_t esp2;
|
||||||
|
uint32_t ss2;
|
||||||
|
uint32_t cr3;
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t eax;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t es;
|
||||||
|
uint32_t cs;
|
||||||
|
uint32_t ss;
|
||||||
|
uint32_t ds;
|
||||||
|
uint32_t fs;
|
||||||
|
uint32_t gs;
|
||||||
|
uint32_t ldt;
|
||||||
|
uint16_t trap;
|
||||||
|
uint16_t iomap_base;
|
||||||
|
} tss_entry;
|
||||||
|
|
||||||
|
void write_tss(int32_t num, uint16_t ss0, uint32_t esp0);
|
||||||
|
|
||||||
|
void gdt_install();
|
||||||
|
void idt_install();
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_DESCRIPTION_TABLE_H
|
11
include/disk.h
Normal file
11
include/disk.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef CPOS_DISK_H
|
||||||
|
#define CPOS_DISK_H
|
||||||
|
|
||||||
|
void wait_disk_ready(); //不适用于SATA硬盘
|
||||||
|
void select_sector(int lba);
|
||||||
|
void read_disk_one_sector(int lba, unsigned int memory_addrress);
|
||||||
|
void write_disk_one_sertor(int lba, unsigned int memory_addrress);
|
||||||
|
void read_disk(int lba, int sector_count, unsigned int memory_addrress);
|
||||||
|
void write_disk(int lba, int sector_count, unsigned int memory_addrress);
|
||||||
|
|
||||||
|
#endif
|
48
include/fat16.h
Normal file
48
include/fat16.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef CPOS_FAT16_H
|
||||||
|
#define CPOS_FAT16_H
|
||||||
|
|
||||||
|
#define SECTOR_SIZE 512
|
||||||
|
#define FAT1_SECTORS 32 //FAT1占用扇区数
|
||||||
|
#define ROOT_DIR_SECTORS 32 //根目录占用扇区数
|
||||||
|
#define SECTOR_NUM_OF_FAT1_START 1 //FAT1起始扇区号
|
||||||
|
#define SECTOR_NUM_OF_ROOT_DIR_START 33 //根目录起始扇区号
|
||||||
|
#define SECTOR_NUM_OF_DATA_START 65 //数据区起始扇区号,对应簇号为2。
|
||||||
|
#define SECTOR_CLUSTER_BALANCE SECTOR_NUM_OF_DATA_START - 2 //簇号加上该值正好对应扇区号。
|
||||||
|
#define MAX_FILE_NUM 16 //最大文件数
|
||||||
|
|
||||||
|
// FAT16目录项结构(32B);
|
||||||
|
struct File {
|
||||||
|
// 文件名 如果第一个字节为0xe5,代表这个文件已经被删除;如果第一个字节为0x00,代表这一段不包含任何文件名信息。
|
||||||
|
unsigned char name[8];
|
||||||
|
unsigned char ext[3]; // 扩展名
|
||||||
|
// 属性:bit0只读文件,bit1隐藏文件,bit2系统文件,bit3非文件信息(比如磁盘名称),bit4目录,bit5文件。
|
||||||
|
unsigned char type; // 0x20 文件 | 0x10 目录
|
||||||
|
unsigned char reserve[10]; // 保留
|
||||||
|
unsigned short time; // 最后一次写入时间
|
||||||
|
unsigned short date; // 最后一次写入日期
|
||||||
|
unsigned short clustno; // 起始簇号
|
||||||
|
unsigned int size; // 文件大小
|
||||||
|
};
|
||||||
|
|
||||||
|
void read_root_dir_sector1(struct File *root_entries);
|
||||||
|
void save_root_dir_sector1(struct File *root_entries);
|
||||||
|
void read_one_cluster(unsigned short clustno, unsigned int memory_addrress);
|
||||||
|
int read_root_dir(struct File *file_infos);
|
||||||
|
void get_fat1(unsigned short *fat1);
|
||||||
|
void save_fat1(unsigned short *fat1);
|
||||||
|
void get_file_all_clustnos(unsigned short first_clustno, unsigned short *clustnos);
|
||||||
|
void get_file_all_clustnos(unsigned short first_clustno, unsigned short *clustnos);
|
||||||
|
void read_file(struct File *file, void *file_addr);
|
||||||
|
void check_name_or_ext(char *str, int len);
|
||||||
|
void check_name_and_ext(char *name, char *ext);
|
||||||
|
void analyse_fullname(char *fullname, char *name, char *ext);
|
||||||
|
int find_file(char *name, char *ext, struct File *const file);
|
||||||
|
struct File *create_file(char *fullname);
|
||||||
|
struct File *create_dir(char *fullname);
|
||||||
|
struct File *open_file(char *fullname);
|
||||||
|
void alter_file_name(struct File *file, char *new_fullname);
|
||||||
|
void alter_dir_entry(struct File *file);
|
||||||
|
void save_file(struct File *file, char *content);
|
||||||
|
void delete_file(struct File *file);
|
||||||
|
|
||||||
|
#endif
|
57
include/io.h
Normal file
57
include/io.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef CRASHPOWEROS_IO_H
|
||||||
|
#define CRASHPOWEROS_IO_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void gdt_flush(uint32_t gdtr);
|
||||||
|
|
||||||
|
void io_hlt(void);
|
||||||
|
|
||||||
|
void io_cli(void);
|
||||||
|
|
||||||
|
void io_sti(void);
|
||||||
|
|
||||||
|
void io_stihlt(void);
|
||||||
|
|
||||||
|
int io_in8(int port);
|
||||||
|
|
||||||
|
int io_in16(int port);
|
||||||
|
|
||||||
|
int io_in32(int port);
|
||||||
|
|
||||||
|
void io_out8(int port, int data);
|
||||||
|
|
||||||
|
void io_out16(int port, int data);
|
||||||
|
|
||||||
|
void io_out32(int port, int data);
|
||||||
|
|
||||||
|
int io_load_eflags(void);
|
||||||
|
|
||||||
|
void io_store_eflags(int eflags);
|
||||||
|
|
||||||
|
void load_gdtr(int limit, int addr);
|
||||||
|
|
||||||
|
void load_idtr(int limit, int addr);
|
||||||
|
|
||||||
|
extern char read_port(unsigned short port);
|
||||||
|
|
||||||
|
static inline void outb(uint16_t port, uint8_t data) {
|
||||||
|
asm volatile("outb %b0, %w1" : : "a"(data), "Nd"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void outsw(uint16_t port, const void *addr, uint32_t word_cnt) {
|
||||||
|
asm volatile("cld; rep outsw" : "+S"(addr), "+c"(word_cnt) : "d"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t inb(uint16_t port) {
|
||||||
|
uint8_t data;
|
||||||
|
asm volatile("inb %w1, %b0" : "=a"(data) : "Nd"(port));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void insw(uint16_t port, void *addr, uint32_t word_cnt) {
|
||||||
|
asm volatile("cld; rep insw" : "+D"(addr), "+c"(word_cnt) : "d"(port) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_IO_H
|
35
include/isr.h
Normal file
35
include/isr.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef CPOS_ISR_H
|
||||||
|
#define CPOS_ISR_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct registers {
|
||||||
|
uint32_t ds; // 我们自己弹入的,当前数据段
|
||||||
|
uint32_t edi, esi, ebp, useless, ebx, edx, ecx, eax; // 按pusha顺序
|
||||||
|
// 其中esp一项不会被popa还原至对应寄存器中,因为esp寄存器代表的是当前的栈而不是进入中断前的,因此用useless代替
|
||||||
|
uint32_t int_no, err_code; // 中断代号是自己push的,err_code有的自带,有的不自带
|
||||||
|
uint32_t eip, cs, eflags, esp, ss; // 进入中断时自动压入的
|
||||||
|
} registers_t;
|
||||||
|
|
||||||
|
#define IRQ0 32
|
||||||
|
#define IRQ1 33
|
||||||
|
#define IRQ2 34
|
||||||
|
#define IRQ3 35
|
||||||
|
#define IRQ4 36
|
||||||
|
#define IRQ5 37
|
||||||
|
#define IRQ6 38
|
||||||
|
#define IRQ7 39
|
||||||
|
#define IRQ8 40
|
||||||
|
#define IRQ9 41
|
||||||
|
#define IRQ10 42
|
||||||
|
#define IRQ11 43
|
||||||
|
#define IRQ12 44
|
||||||
|
#define IRQ13 45
|
||||||
|
#define IRQ14 46
|
||||||
|
#define IRQ15 47
|
||||||
|
|
||||||
|
typedef void (*isr_t)(registers_t *);
|
||||||
|
|
||||||
|
void register_interrupt_handler(uint8_t n, isr_t handler);
|
||||||
|
|
||||||
|
#endif
|
19
include/keyboard.h
Normal file
19
include/keyboard.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef CRASHPOWEROS_KEYBOARD_H
|
||||||
|
#define CRASHPOWEROS_KEYBOARD_H
|
||||||
|
|
||||||
|
#define KEYBOARD_DATA_PORT 0x60
|
||||||
|
#define KEYBOARD_STATUS_PORT 0x64
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int is_shift;
|
||||||
|
}KEY_STATUS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *keyboard_map[128];
|
||||||
|
unsigned char *shift_keyboard_map[128];
|
||||||
|
}KEY_MAP;
|
||||||
|
|
||||||
|
void init_keyboard();
|
||||||
|
int handle_keyboard_input();
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_KEYBOARD_H
|
82
include/memory.h
Normal file
82
include/memory.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef CRASHPOWEROS_MEMORY_H
|
||||||
|
#define CRASHPOWEROS_MEMORY_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "isr.h"
|
||||||
|
|
||||||
|
#define KHEAP_INITIAL_SIZE 0xf00000
|
||||||
|
#define KHEAP_START 0xc0000000
|
||||||
|
#define STACK_SIZE 32768
|
||||||
|
|
||||||
|
#define INDEX_FROM_BIT(a) (a / (8*4))
|
||||||
|
#define OFFSET_FROM_BIT(a) (a % (8*4))
|
||||||
|
|
||||||
|
typedef char ALIGN[16];
|
||||||
|
|
||||||
|
typedef struct page {
|
||||||
|
uint32_t present: 1;
|
||||||
|
uint32_t rw: 1;
|
||||||
|
uint32_t user: 1;
|
||||||
|
uint32_t accessed: 1;
|
||||||
|
uint32_t dirty: 1;
|
||||||
|
uint32_t unused: 7;
|
||||||
|
uint32_t frame: 20;
|
||||||
|
} page_t;
|
||||||
|
|
||||||
|
typedef struct page_table {
|
||||||
|
page_t pages[1024];
|
||||||
|
} page_table_t;
|
||||||
|
|
||||||
|
typedef struct page_directory {
|
||||||
|
page_table_t *tables[1024];
|
||||||
|
uint32_t tablesPhysical[1024];
|
||||||
|
uint32_t physicalAddr;
|
||||||
|
} page_directory_t;
|
||||||
|
|
||||||
|
typedef union header {
|
||||||
|
struct {
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t is_free;
|
||||||
|
union header *next;
|
||||||
|
} s;
|
||||||
|
ALIGN stub;
|
||||||
|
} header_t;
|
||||||
|
|
||||||
|
void *memcpy(void *dst_, const void *src_, uint32_t size);
|
||||||
|
|
||||||
|
int memcmp(const void *a_, const void *b_, uint32_t size);
|
||||||
|
|
||||||
|
void *memset(void *s, int c, size_t n);
|
||||||
|
|
||||||
|
void *memmove(void *dest, const void *src, size_t num);
|
||||||
|
|
||||||
|
void switch_page_directory(page_directory_t *dir);
|
||||||
|
|
||||||
|
page_t *get_page(uint32_t address, int make, page_directory_t *dir);
|
||||||
|
|
||||||
|
void alloc_frame(page_t *page, int is_kernel, int is_writable);
|
||||||
|
|
||||||
|
uint32_t first_frame();
|
||||||
|
|
||||||
|
void page_fault(registers_t *regs);
|
||||||
|
|
||||||
|
void flush_tlb();
|
||||||
|
|
||||||
|
void *ksbrk(int incr);
|
||||||
|
|
||||||
|
void *alloc(uint32_t size);
|
||||||
|
|
||||||
|
void kfree(void *ptr);
|
||||||
|
|
||||||
|
uint32_t kmalloc_a(uint32_t size);
|
||||||
|
|
||||||
|
uint32_t kmalloc_p(uint32_t size, uint32_t *phy);
|
||||||
|
|
||||||
|
uint32_t kmalloc(size_t size);
|
||||||
|
|
||||||
|
uint32_t kmalloc_ap(uint32_t size, uint32_t *phys);
|
||||||
|
|
||||||
|
void init_page();
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_MEMORY_H
|
20
include/queue.h
Normal file
20
include/queue.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef CPOS_QUEUE_H
|
||||||
|
#define CPOS_QUEUE_H
|
||||||
|
|
||||||
|
typedef struct queue_node {
|
||||||
|
char data;
|
||||||
|
struct queue_node *next;
|
||||||
|
}QNode;
|
||||||
|
|
||||||
|
typedef struct queue {
|
||||||
|
QNode *phead; //队头
|
||||||
|
QNode *ptail; //队尾
|
||||||
|
int size;
|
||||||
|
}Queue;
|
||||||
|
|
||||||
|
Queue *create_queue();
|
||||||
|
void free_queue(Queue *queue);
|
||||||
|
char queue_pop(Queue *pq);
|
||||||
|
void queue_push(Queue *pq, char x);
|
||||||
|
|
||||||
|
#endif
|
16
include/shell.h
Normal file
16
include/shell.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef CRASHPOWEROS_SHELL_H
|
||||||
|
#define CRASHPOWEROS_SHELL_H
|
||||||
|
|
||||||
|
#define MAX_COMMAND_LEN 100
|
||||||
|
#define MAX_ARG_NR 50
|
||||||
|
|
||||||
|
char getc();
|
||||||
|
int gets(char *buf, int buf_size);
|
||||||
|
void setup_shell();
|
||||||
|
|
||||||
|
//内置命令
|
||||||
|
void cmd_echo(int argc,char **argv);
|
||||||
|
void cmd_proc();
|
||||||
|
void cmd_date();
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_SHELL_H
|
50
include/task.h
Normal file
50
include/task.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef CRASHPOWEROS_TASK_H
|
||||||
|
#define CRASHPOWEROS_TASK_H
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
typedef
|
||||||
|
enum task_state {
|
||||||
|
TASK_UNINIT = 0, // 未初始化
|
||||||
|
TASK_SLEEPING = 1, // 睡眠中
|
||||||
|
TASK_RUNNABLE = 2, // 可运行(也许正在运行)
|
||||||
|
TASK_ZOMBIE = 3, // 僵尸状态
|
||||||
|
} task_state;
|
||||||
|
|
||||||
|
struct context {
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t eflags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mm_struct {
|
||||||
|
page_directory_t *pgd_dir; // 进程页表
|
||||||
|
};
|
||||||
|
|
||||||
|
// 进程控制块 PCB
|
||||||
|
struct task_struct {
|
||||||
|
volatile task_state state; // 进程当前状态
|
||||||
|
int pid; // 进程标识符
|
||||||
|
char *name; // 进程名
|
||||||
|
void *stack; // 进程的内核栈地址
|
||||||
|
struct mm_struct *mm; // 当前进程的内存地址映像
|
||||||
|
struct context context; // 进程切换需要的上下文信息
|
||||||
|
struct task_struct *next; // 链表指针
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t kernel_thread(int (*fn)(void *), void *arg, char *name);
|
||||||
|
|
||||||
|
void kthread_exit();
|
||||||
|
|
||||||
|
void print_proc();
|
||||||
|
|
||||||
|
void init_sched();
|
||||||
|
|
||||||
|
void schedule();
|
||||||
|
|
||||||
|
void change_task_to(struct task_struct *next);
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_TASK_H
|
10
include/timer.h
Normal file
10
include/timer.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef CRASHPOWEROS_TIMER_H
|
||||||
|
#define CRASHPOWEROS_TIMER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void init_timer(uint32_t timer);
|
||||||
|
|
||||||
|
void clock_sleep(uint32_t timer);
|
||||||
|
|
||||||
|
#endif //CRASHPOWEROS_TIMER_H
|
65
include/vga.h
Normal file
65
include/vga.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#ifndef CPOS_VGA_H
|
||||||
|
#define CPOS_VGA_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#define FLAG_ALTNT_FORM 0x01
|
||||||
|
#define FLAG_ALTNT_FORM_CH '#'
|
||||||
|
|
||||||
|
#define FLAG_ZERO_PAD 0x02
|
||||||
|
#define FLAG_ZERO_PAD_CH '0'
|
||||||
|
|
||||||
|
#define FLAG_LEFT_ADJUST 0x04
|
||||||
|
#define FLAG_LEFT_ADJUST_CH '-'
|
||||||
|
|
||||||
|
#define FLAG_SPACE_BEFORE_POS_NUM 0x08
|
||||||
|
#define FLAG_SPACE_BEFORE_POS_NUM_CH ' '
|
||||||
|
|
||||||
|
#define FLAG_SIGN 0x10
|
||||||
|
#define FLAG_SIGN_CH '+'
|
||||||
|
|
||||||
|
#define FLAG_LOWER 0x20
|
||||||
|
|
||||||
|
#define INT_TYPE_CHAR 0x1
|
||||||
|
#define INT_TYPE_SHORT 0x2
|
||||||
|
#define INT_TYPE_INT 0x4
|
||||||
|
#define INT_TYPE_LONG 0x8
|
||||||
|
#define INT_TYPE_LONG_LONG 0x10
|
||||||
|
#define INT_TYPE_MIN INT_TYPE_CHAR
|
||||||
|
#define INT_TYPE_MAX INT_TYPE_LONG_LONG
|
||||||
|
|
||||||
|
#define BUF_SIZE 4096
|
||||||
|
|
||||||
|
enum vga_color {
|
||||||
|
VGA_COLOR_BLACK = 0,
|
||||||
|
VGA_COLOR_BLUE = 1,
|
||||||
|
VGA_COLOR_GREEN = 2,
|
||||||
|
VGA_COLOR_CYAN = 3,
|
||||||
|
VGA_COLOR_RED = 4,
|
||||||
|
VGA_COLOR_MAGENTA = 5,
|
||||||
|
VGA_COLOR_BROWN = 6,
|
||||||
|
VGA_COLOR_LIGHT_GREY = 7,
|
||||||
|
VGA_COLOR_DARK_GREY = 8,
|
||||||
|
VGA_COLOR_LIGHT_BLUE = 9,
|
||||||
|
VGA_COLOR_LIGHT_GREEN = 10,
|
||||||
|
VGA_COLOR_LIGHT_CYAN = 11,
|
||||||
|
VGA_COLOR_LIGHT_RED = 12,
|
||||||
|
VGA_COLOR_LIGHT_MAGENTA = 13,
|
||||||
|
VGA_COLOR_LIGHT_BROWN = 14,
|
||||||
|
VGA_COLOR_WHITE = 15,
|
||||||
|
};
|
||||||
|
|
||||||
|
void vga_install(void);
|
||||||
|
void vga_setcolor(uint8_t color);
|
||||||
|
void vga_putentryat(char c, uint8_t color, size_t x, size_t y);
|
||||||
|
void vga_putchar(char c);
|
||||||
|
void vga_write(const char* data, size_t size);
|
||||||
|
void vga_writestring(const char* data);
|
||||||
|
void vga_write_dec(uint32_t dec);
|
||||||
|
void vga_clear();
|
||||||
|
void move_cursor();
|
||||||
|
void printf(const char *formet, ...);
|
||||||
|
|
||||||
|
#endif
|
578
kernel/common.c
Normal file
578
kernel/common.c
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
#include "../include/common.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
static char num_str_buf[BUF_SIZE];
|
||||||
|
|
||||||
|
int sprintf(char *buf, const char *fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
int retval;
|
||||||
|
va_start(args, fmt);
|
||||||
|
retval = vsprintf(buf, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strlen(const char *str) {
|
||||||
|
size_t len = 0;
|
||||||
|
while (str[len])
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp(const char *s1, const char *s2) {
|
||||||
|
char is_equal = 1;
|
||||||
|
|
||||||
|
for (; (*s1 != '\0') && (*s2 != '\0'); s1++, s2++) {
|
||||||
|
if (*s1 != *s2) {
|
||||||
|
is_equal = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_equal) {
|
||||||
|
if (*s1 != '\0') {
|
||||||
|
return 1;
|
||||||
|
} else if (*s2 != '\0') {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (int) (*s1 - *s2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strcpy(char *dest, const char *src) {
|
||||||
|
do {
|
||||||
|
*dest++ = *src++;
|
||||||
|
} while (*src != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strcat(char *dest, const char *src) {
|
||||||
|
char *temp = dest;
|
||||||
|
while (*temp != '\0')
|
||||||
|
temp++;
|
||||||
|
while ((*temp++ = *src++) != '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
int isspace(int c) {
|
||||||
|
return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' ||
|
||||||
|
c == '\v');
|
||||||
|
}
|
||||||
|
|
||||||
|
// isdigit
|
||||||
|
int isdigit(int c) {
|
||||||
|
return (c >= '0' && c <= '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
// isalpha
|
||||||
|
int isalpha(int c) {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
// isupper
|
||||||
|
int isupper(int c) {
|
||||||
|
return (c >= 'A' && c <= 'Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
char *int32_to_str_dec(int32_t num, int flag, int width) {
|
||||||
|
int32_t num_tmp = num;
|
||||||
|
char *p = num_str_buf;
|
||||||
|
char *q = NULL;
|
||||||
|
int len = 0;
|
||||||
|
char *str_first = NULL;
|
||||||
|
char *str_end = NULL;
|
||||||
|
char ch = 0;
|
||||||
|
|
||||||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||||||
|
|
||||||
|
char dic[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||||
|
|
||||||
|
if (num_tmp < 0) {
|
||||||
|
*p++ = '-';
|
||||||
|
} else if (flag & FLAG_SIGN) {
|
||||||
|
*p++ = '+';
|
||||||
|
} else {
|
||||||
|
*p++ = ' ';
|
||||||
|
}
|
||||||
|
str_first = num_str_buf;
|
||||||
|
|
||||||
|
if (num_tmp >= 0 && !(flag & FLAG_SIGN)) {
|
||||||
|
str_first++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_tmp == 0) {
|
||||||
|
*p++ = '0';
|
||||||
|
} else {
|
||||||
|
if (num_tmp < 0)
|
||||||
|
num_tmp = -num_tmp;
|
||||||
|
|
||||||
|
while (num_tmp) {
|
||||||
|
*p++ = dic[num_tmp % 10];
|
||||||
|
num_tmp /= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
str_end = p;
|
||||||
|
len = str_end - str_first;
|
||||||
|
|
||||||
|
q = num_str_buf + 1;
|
||||||
|
p--;
|
||||||
|
while (q < p) {
|
||||||
|
ch = *q;
|
||||||
|
*q = *p;
|
||||||
|
*p = ch;
|
||||||
|
p--;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < width) {
|
||||||
|
p = str_end;
|
||||||
|
|
||||||
|
if (flag & FLAG_LEFT_ADJUST) {
|
||||||
|
for (int i = 0; i < width - len; i++)
|
||||||
|
*p++ = ' ';
|
||||||
|
*p = '\0';
|
||||||
|
str_end = p;
|
||||||
|
} else {
|
||||||
|
while (p >= str_first) {
|
||||||
|
*(p + width - len) = *p;
|
||||||
|
p--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & FLAG_ZERO_PAD) {
|
||||||
|
for (int i = 0; i < width - len; i++) {
|
||||||
|
num_str_buf[i + 1] = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < width - len; i++)
|
||||||
|
str_first[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_first;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *int64_to_str_dec(int64_t num, int flag, int width) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *uint32_to_str_hex(uint32_t num, int flag, int width) {
|
||||||
|
uint32_t num_tmp = num;
|
||||||
|
char *p = num_str_buf;
|
||||||
|
char *q = NULL;
|
||||||
|
int len = 0;
|
||||||
|
char *str_first = NULL;
|
||||||
|
char *str_end = NULL;
|
||||||
|
char ch = 0;
|
||||||
|
|
||||||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||||||
|
|
||||||
|
char dic_lower[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
char dic_upper[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
char *dic = (flag & FLAG_LOWER) ? dic_lower : dic_upper;
|
||||||
|
|
||||||
|
str_first = num_str_buf;
|
||||||
|
|
||||||
|
*p++ = '0';
|
||||||
|
*p++ = (flag & FLAG_LOWER) ? 'x' : 'X';
|
||||||
|
|
||||||
|
if (!(flag & FLAG_ALTNT_FORM)) {
|
||||||
|
str_first += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
*p++ = dic[num_tmp % 16];
|
||||||
|
num_tmp /= 16;
|
||||||
|
} while (num_tmp);
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
str_end = p;
|
||||||
|
len = str_end - str_first;
|
||||||
|
|
||||||
|
q = num_str_buf + 2;
|
||||||
|
p--;
|
||||||
|
while (q < p) {
|
||||||
|
ch = *q;
|
||||||
|
*q = *p;
|
||||||
|
*p = ch;
|
||||||
|
p--;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < width) {
|
||||||
|
p = str_end;
|
||||||
|
|
||||||
|
if (flag & FLAG_LEFT_ADJUST) {
|
||||||
|
for (int i = 0; i < width - len; i++)
|
||||||
|
*p++ = ' ';
|
||||||
|
*p = '\0';
|
||||||
|
str_end = p;
|
||||||
|
} else {
|
||||||
|
while (p >= str_first) {
|
||||||
|
*(p + width - len) = *p;
|
||||||
|
p--;
|
||||||
|
}
|
||||||
|
if (flag & FLAG_ALTNT_FORM)
|
||||||
|
str_first[1] = (flag & FLAG_LOWER) ? 'x' : 'X';
|
||||||
|
|
||||||
|
if (flag & FLAG_ZERO_PAD) {
|
||||||
|
for (int i = 0; i < width - len; i++) {
|
||||||
|
num_str_buf[i + 2] = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < width - len; i++)
|
||||||
|
str_first[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num == 0 && flag & FLAG_ALTNT_FORM)
|
||||||
|
str_first[1] = '0';
|
||||||
|
|
||||||
|
return str_first;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *uint64_to_str_hex(uint64_t num, int flag, int width) {
|
||||||
|
uint64_t num_tmp = num;
|
||||||
|
char *p = num_str_buf;
|
||||||
|
char *q = NULL;
|
||||||
|
int len = 0;
|
||||||
|
char *str_first = NULL;
|
||||||
|
char *str_end = NULL;
|
||||||
|
char ch = 0;
|
||||||
|
|
||||||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||||||
|
|
||||||
|
char dic_lower[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
char dic_upper[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
char *dic = (flag & FLAG_LOWER) ? dic_lower : dic_upper;
|
||||||
|
|
||||||
|
str_first = num_str_buf;
|
||||||
|
|
||||||
|
*p++ = '0';
|
||||||
|
*p++ = (flag & FLAG_LOWER) ? 'x' : 'X';
|
||||||
|
|
||||||
|
if (!(flag & FLAG_ALTNT_FORM)) {
|
||||||
|
str_first += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (num_tmp) {
|
||||||
|
*p++ = dic[num_tmp % 16];
|
||||||
|
num_tmp /= 16;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
str_end = p;
|
||||||
|
len = str_end - str_first;
|
||||||
|
|
||||||
|
q = num_str_buf + 2;
|
||||||
|
p--;
|
||||||
|
while (q < p) {
|
||||||
|
ch = *q;
|
||||||
|
*q = *p;
|
||||||
|
*p = ch;
|
||||||
|
p--;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < width) {
|
||||||
|
p = str_end;
|
||||||
|
|
||||||
|
while (p >= str_first) {
|
||||||
|
*(p + width - len) = *p;
|
||||||
|
p--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & FLAG_ZERO_PAD) {
|
||||||
|
for (int i = 0; i < width - len; i++) {
|
||||||
|
num_str_buf[i + 2] = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < width - len; i++)
|
||||||
|
str_first[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_first;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *uint32_to_str_oct(uint32_t num, int flag, int width) {
|
||||||
|
uint32_t num_tmp = num;
|
||||||
|
char *p = num_str_buf;
|
||||||
|
char *q = NULL;
|
||||||
|
int len = 0;
|
||||||
|
char *str_first = NULL;
|
||||||
|
char *str_end = NULL;
|
||||||
|
char ch = 0;
|
||||||
|
|
||||||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||||||
|
|
||||||
|
char dic[] = {'0', '1', '2', '3', '4', '5', '6', '7'};
|
||||||
|
|
||||||
|
str_first = num_str_buf;
|
||||||
|
|
||||||
|
*p++ = '0';
|
||||||
|
|
||||||
|
if (!(flag & FLAG_ALTNT_FORM)) {
|
||||||
|
str_first += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (num_tmp) {
|
||||||
|
*p++ = dic[num_tmp % 8];
|
||||||
|
num_tmp /= 8;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
str_end = p;
|
||||||
|
len = str_end - str_first;
|
||||||
|
|
||||||
|
q = num_str_buf + 1;
|
||||||
|
p--;
|
||||||
|
while (q < p) {
|
||||||
|
ch = *q;
|
||||||
|
*q = *p;
|
||||||
|
*p = ch;
|
||||||
|
p--;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < width) {
|
||||||
|
p = str_end;
|
||||||
|
|
||||||
|
if (flag & FLAG_LEFT_ADJUST) {
|
||||||
|
for (int i = 0; i < width - len; i++)
|
||||||
|
*p++ = ' ';
|
||||||
|
*p = '\0';
|
||||||
|
str_end = p;
|
||||||
|
} else {
|
||||||
|
while (p >= str_first) {
|
||||||
|
*(p + width - len) = *p;
|
||||||
|
p--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag & FLAG_ZERO_PAD) {
|
||||||
|
for (int i = 0; i < width - len; i++) {
|
||||||
|
num_str_buf[i + 1] = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < width - len; i++)
|
||||||
|
str_first[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_first;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *insert_str(char *buf, const char *str) {
|
||||||
|
char *p = buf;
|
||||||
|
|
||||||
|
while (*str) {
|
||||||
|
*p++ = *str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsprintf(char *buf, const char *fmt, va_list args) {
|
||||||
|
char *str = buf;
|
||||||
|
int flag = 0;
|
||||||
|
int int_type = INT_TYPE_INT;
|
||||||
|
int tot_width = 0;
|
||||||
|
int sub_width = 0;
|
||||||
|
char buf2[64] = {0};
|
||||||
|
char *s = NULL;
|
||||||
|
char ch = 0;
|
||||||
|
int8_t num_8 = 0;
|
||||||
|
uint8_t num_u8 = 0;
|
||||||
|
int16_t num_16 = 0;
|
||||||
|
uint16_t num_u16 = 0;
|
||||||
|
int32_t num_32 = 0;
|
||||||
|
uint32_t num_u32 = 0;
|
||||||
|
int64_t num_64 = 0;
|
||||||
|
uint64_t num_u64 = 0;
|
||||||
|
|
||||||
|
for (const char *p = fmt; *p; p++) {
|
||||||
|
if (*p != '%') {
|
||||||
|
*str++ = *p;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = 0;
|
||||||
|
tot_width = 0;
|
||||||
|
sub_width = 0;
|
||||||
|
int_type = INT_TYPE_INT;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
|
||||||
|
while (*p == FLAG_ALTNT_FORM_CH || *p == FLAG_ZERO_PAD_CH ||
|
||||||
|
*p == FLAG_LEFT_ADJUST_CH || *p == FLAG_SPACE_BEFORE_POS_NUM_CH ||
|
||||||
|
*p == FLAG_SIGN_CH) {
|
||||||
|
if (*p == FLAG_ALTNT_FORM_CH) {
|
||||||
|
flag |= FLAG_ALTNT_FORM;
|
||||||
|
} else if (*p == FLAG_ZERO_PAD_CH) {
|
||||||
|
flag |= FLAG_ZERO_PAD;
|
||||||
|
} else if (*p == FLAG_LEFT_ADJUST_CH) {
|
||||||
|
flag |= FLAG_LEFT_ADJUST;
|
||||||
|
flag &= ~FLAG_ZERO_PAD;
|
||||||
|
} else if (*p == FLAG_SPACE_BEFORE_POS_NUM_CH) {
|
||||||
|
flag |= FLAG_SPACE_BEFORE_POS_NUM;
|
||||||
|
} else if (*p == FLAG_SIGN_CH) {
|
||||||
|
flag |= FLAG_SIGN;
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == '*') {
|
||||||
|
tot_width = va_arg(args,
|
||||||
|
int);
|
||||||
|
if (tot_width < 0)
|
||||||
|
tot_width = 0;
|
||||||
|
p++;
|
||||||
|
} else {
|
||||||
|
while (isdigit(*p)) {
|
||||||
|
tot_width = tot_width * 10 + *p - '0';
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*p == '.') {
|
||||||
|
if (*p == '*') {
|
||||||
|
sub_width = va_arg(args,
|
||||||
|
int);
|
||||||
|
if (sub_width < 0)
|
||||||
|
sub_width = 0;
|
||||||
|
p++;
|
||||||
|
} else {
|
||||||
|
while (isdigit(*p)) {
|
||||||
|
sub_width = sub_width * 10 + *p - '0';
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOOP_switch:
|
||||||
|
switch (*p) {
|
||||||
|
case 'h':
|
||||||
|
p++;
|
||||||
|
if (int_type >= INT_TYPE_MIN) {
|
||||||
|
int_type >>= 1;
|
||||||
|
goto LOOP_switch;
|
||||||
|
} else {
|
||||||
|
*str++ = '%';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'l':
|
||||||
|
p++;
|
||||||
|
if (int_type <= INT_TYPE_MAX) {
|
||||||
|
int_type <<= 1;
|
||||||
|
goto LOOP_switch;
|
||||||
|
} else {
|
||||||
|
*str++ = '%';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
s = va_arg(args,
|
||||||
|
char *);
|
||||||
|
str = insert_str(str, s);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
ch = (char) (va_arg(args,
|
||||||
|
int) &
|
||||||
|
0xFF);
|
||||||
|
*str++ = ch;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
switch (int_type) {
|
||||||
|
case INT_TYPE_CHAR:
|
||||||
|
num_8 = (int8_t) va_arg(args, int32_t);
|
||||||
|
str = insert_str(str, int32_to_str_dec(num_8, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_SHORT:
|
||||||
|
num_16 = (int16_t) va_arg(args, int32_t);
|
||||||
|
str = insert_str(str, int32_to_str_dec(num_16, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_INT:
|
||||||
|
num_32 = va_arg(args, int32_t);
|
||||||
|
str = insert_str(str, int32_to_str_dec(num_32, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_LONG:
|
||||||
|
num_64 = va_arg(args, int64_t);
|
||||||
|
str = insert_str(str, int64_to_str_dec(num_64, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_LONG_LONG:
|
||||||
|
num_64 = va_arg(args, int64_t);
|
||||||
|
str = insert_str(str, int64_to_str_dec(num_64, flag, tot_width));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
flag |= FLAG_LOWER;
|
||||||
|
case 'X':
|
||||||
|
switch (int_type) {
|
||||||
|
case INT_TYPE_CHAR:
|
||||||
|
num_u8 = (uint8_t)
|
||||||
|
va_arg(args, uint32_t);
|
||||||
|
str = insert_str(str, uint32_to_str_hex(num_u8, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_SHORT:
|
||||||
|
num_u16 = (uint16_t)
|
||||||
|
va_arg(args, uint32_t);
|
||||||
|
str = insert_str(str, uint32_to_str_hex(num_u16, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_INT:
|
||||||
|
num_u32 = va_arg(args, uint32_t);
|
||||||
|
str = insert_str(str, uint32_to_str_hex(num_u32, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_LONG:
|
||||||
|
num_u64 = va_arg(args, uint64_t);
|
||||||
|
str = insert_str(str, uint64_to_str_hex(num_u64, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case INT_TYPE_LONG_LONG:
|
||||||
|
num_u64 = va_arg(args, uint64_t);
|
||||||
|
str = insert_str(str, uint64_to_str_hex(num_u64, flag, tot_width));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
num_u32 = va_arg(args, uint32_t);
|
||||||
|
str = insert_str(str, uint32_to_str_oct(num_u32, flag, tot_width));
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
*str++ = '%';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*str++ = '%';
|
||||||
|
*str++ = *p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*str = '\0';
|
||||||
|
|
||||||
|
return str - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert(int b,char* message){
|
||||||
|
if(!b){
|
||||||
|
printf("[KERNEL-PANIC]: %s",message);
|
||||||
|
while (1) io_hlt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void trim(char *s){
|
||||||
|
char *p = s;
|
||||||
|
int len = strlen(p);
|
||||||
|
while (isspace(p[len - 1])) p[--len] = 0;
|
||||||
|
while (*p && isspace(*p)) ++p,--len;
|
||||||
|
memmove(s,p,len+1);
|
||||||
|
}
|
327
kernel/fat16.c
Normal file
327
kernel/fat16.c
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
#include "../include/fat16.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/disk.h"
|
||||||
|
|
||||||
|
void read_root_dir_sector1(struct File *root_entries) {
|
||||||
|
read_disk(SECTOR_NUM_OF_ROOT_DIR_START, 1, (unsigned int) root_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_root_dir_sector1(struct File *root_entries) {
|
||||||
|
write_disk(SECTOR_NUM_OF_ROOT_DIR_START, 1, (unsigned int) root_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_one_cluster(unsigned short clustno, unsigned int memory_addrress) {
|
||||||
|
read_disk(clustno + SECTOR_CLUSTER_BALANCE, 1, memory_addrress);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_root_dir(struct File *file_infos) {
|
||||||
|
struct File *root_entries = (struct File *) kmalloc(SECTOR_SIZE);
|
||||||
|
read_root_dir_sector1(root_entries);
|
||||||
|
int n = 0; // 记录文件数
|
||||||
|
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
||||||
|
if (root_entries[i].name[0] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (root_entries[i].name[0] != 0xe5) {
|
||||||
|
file_infos[n] = root_entries[i];
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree(root_entries);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_fat1(unsigned short *fat1) {
|
||||||
|
read_disk(SECTOR_NUM_OF_FAT1_START, FAT1_SECTORS, (unsigned int) fat1); // 将FAT1全部读取到内存中。
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_fat1(unsigned short *fat1) {
|
||||||
|
write_disk(SECTOR_NUM_OF_FAT1_START, FAT1_SECTORS, (unsigned int) fat1); // 将FAT1全部写回到内存中。
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_file_all_clustnos(unsigned short first_clustno, unsigned short *clustnos) {
|
||||||
|
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
|
||||||
|
get_fat1(fat1);
|
||||||
|
*clustnos = first_clustno;
|
||||||
|
while (1) {
|
||||||
|
unsigned short clustno = *(fat1 + *clustnos);
|
||||||
|
clustnos++;
|
||||||
|
*clustnos = clustno;
|
||||||
|
if (clustno >= 0xfff8) // 大于等于0xfff8表示文件的最后一个簇
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree(fat1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_file(struct File *file, void *file_addr) {
|
||||||
|
if (file->size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int cluster_count = (file->size + 511) / 512;
|
||||||
|
unsigned short *clustnos = kmalloc(cluster_count * 2);
|
||||||
|
get_file_all_clustnos(file->clustno, clustnos);
|
||||||
|
for (int i = 0; i < cluster_count; i++) {
|
||||||
|
read_one_cluster(clustnos[i], (unsigned int) file_addr);
|
||||||
|
file_addr += 512;
|
||||||
|
}
|
||||||
|
kfree(clustnos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_name_or_ext(char *str, int len) {
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (str[i] == 0) {
|
||||||
|
str[i] = ' ';
|
||||||
|
} else if ('a' <= str[i] && str[i] <= 'z') {
|
||||||
|
str[i] -= 0x20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_name_and_ext(char *name, char *ext) {
|
||||||
|
check_name_or_ext(name, 8);
|
||||||
|
check_name_or_ext(ext, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void analyse_fullname(char *fullname, char *name, char *ext) {
|
||||||
|
int ext_dot_index = -1;
|
||||||
|
for (int i = 11; i >= 0; i--) {
|
||||||
|
if (fullname[i] == '.') {
|
||||||
|
ext_dot_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ext_dot_index == -1) // 没有后缀名的情况
|
||||||
|
{
|
||||||
|
memcpy(name, fullname, 8);
|
||||||
|
memset(ext, ' ', 3);
|
||||||
|
} else if (ext_dot_index == 0) // 没有文件名的情况
|
||||||
|
{
|
||||||
|
memset(name, ' ', 8);
|
||||||
|
memcpy(ext, fullname + 1, 3);
|
||||||
|
} else {
|
||||||
|
memcpy(name, fullname, ext_dot_index);
|
||||||
|
memcpy(ext, fullname + ext_dot_index + 1, 3);
|
||||||
|
}
|
||||||
|
check_name_and_ext(name, ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_file(char *name, char *ext, struct File *const file) {
|
||||||
|
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
||||||
|
read_root_dir_sector1(root_entries);
|
||||||
|
int isfind = 0;
|
||||||
|
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
||||||
|
if (memcmp(root_entries[i].name, name, 8) == 0 && memcmp(root_entries[i].ext, ext, 3) == 0) {
|
||||||
|
if (file != 0) {
|
||||||
|
*file = root_entries[i];
|
||||||
|
}
|
||||||
|
isfind = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree(root_entries);
|
||||||
|
return isfind;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct File *create_dir(char *fullname) {
|
||||||
|
char name[8] = {0};
|
||||||
|
char ext[3] = {0};
|
||||||
|
analyse_fullname(fullname, name, ext);
|
||||||
|
int isfind = find_file(name, ext, 0);
|
||||||
|
if (isfind) {
|
||||||
|
return 0; //文件已存在。
|
||||||
|
}
|
||||||
|
|
||||||
|
struct File *file = (struct File *) kmalloc(32);
|
||||||
|
memcpy(file->name, name, 8);
|
||||||
|
memcpy(file->ext, " ", 3);
|
||||||
|
file->type = 0x10;
|
||||||
|
file->time = 0;
|
||||||
|
file->date = 0;
|
||||||
|
file->clustno = 0;
|
||||||
|
file->size = 0;
|
||||||
|
|
||||||
|
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
||||||
|
read_root_dir_sector1(root_entries);
|
||||||
|
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
||||||
|
if (root_entries[i].name[0] == 0 || root_entries[i].name[0] == 0xe5) { //找一个空闲的文件项存放。
|
||||||
|
root_entries[i] = *file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save_root_dir_sector1(root_entries);
|
||||||
|
kfree(root_entries);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct File *create_file(char *fullname) {
|
||||||
|
char name[8] = {0};
|
||||||
|
char ext[3] = {0};
|
||||||
|
analyse_fullname(fullname, name, ext);
|
||||||
|
int isfind = find_file(name, ext, 0);
|
||||||
|
if (isfind) {
|
||||||
|
return 0; //文件已存在。
|
||||||
|
}
|
||||||
|
|
||||||
|
struct File *file = (struct File *) kmalloc(32);
|
||||||
|
memcpy(file->name, name, 8);
|
||||||
|
memcpy(file->ext, ext, 3);
|
||||||
|
file->type = 0x20;
|
||||||
|
file->time = 0;
|
||||||
|
file->date = 0;
|
||||||
|
file->clustno = 0;
|
||||||
|
file->size = 0;
|
||||||
|
|
||||||
|
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
||||||
|
read_root_dir_sector1(root_entries);
|
||||||
|
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
||||||
|
if (root_entries[i].name[0] == 0 || root_entries[i].name[0] == 0xe5) { //找一个空闲的文件项存放。
|
||||||
|
root_entries[i] = *file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save_root_dir_sector1(root_entries);
|
||||||
|
|
||||||
|
kfree(root_entries);
|
||||||
|
//open_file_task(file);
|
||||||
|
kfree(name);
|
||||||
|
kfree(ext);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct File *open_file(char *fullname) {
|
||||||
|
char name[8] = {0};
|
||||||
|
char ext[3] = {0};
|
||||||
|
analyse_fullname(fullname, name, ext);
|
||||||
|
struct File *file = (struct File *) kmalloc(32);
|
||||||
|
int isfind = find_file(name, ext, file);
|
||||||
|
if (!isfind) {
|
||||||
|
kfree(file);
|
||||||
|
file = 0;
|
||||||
|
} else {
|
||||||
|
//set_opened_file(file);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void alter_file_name(struct File *file, char *new_fullname) {
|
||||||
|
char new_name[8] = {0};
|
||||||
|
char new_ext[3] = {0};
|
||||||
|
analyse_fullname(new_fullname, new_name, new_ext);
|
||||||
|
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
||||||
|
read_root_dir_sector1(root_entries);
|
||||||
|
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
||||||
|
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
|
||||||
|
memcpy(root_entries[i].name, new_name, 8);
|
||||||
|
memcpy(root_entries[i].ext, new_ext, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save_root_dir_sector1(root_entries);
|
||||||
|
kfree(root_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void alter_dir_entry(struct File *file) {
|
||||||
|
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
||||||
|
read_root_dir_sector1(root_entries);
|
||||||
|
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
||||||
|
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
|
||||||
|
root_entries[i] = *file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save_root_dir_sector1(root_entries);
|
||||||
|
kfree(root_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_file(struct File *file, char *content) {
|
||||||
|
unsigned int file_size = strlen(content); //内容大小
|
||||||
|
if (file_size == 0 && file->size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
file->size = file_size;
|
||||||
|
int sector_num = (file_size + 511) / 512; //将要占用的扇区数
|
||||||
|
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
|
||||||
|
get_fat1(fat1);
|
||||||
|
unsigned short clustno = file->clustno;
|
||||||
|
unsigned short next_clustno;
|
||||||
|
if (file->clustno == 0) //第一次写入
|
||||||
|
{
|
||||||
|
clustno = 2; //可用簇号从2开始
|
||||||
|
while (1) {
|
||||||
|
if (*(fat1 + clustno) == 0) //空闲簇号
|
||||||
|
{
|
||||||
|
file->clustno = clustno; //分配起始簇号
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
clustno++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
while (1) {
|
||||||
|
write_disk(SECTOR_CLUSTER_BALANCE + clustno, 1, (unsigned int) content);
|
||||||
|
if (i == sector_num - 1) { //已写完最后一扇区。
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
content += 512;
|
||||||
|
next_clustno = *(fat1 + clustno);
|
||||||
|
if (next_clustno == 0 || next_clustno >= 0xfff8) { //寻找下一个可用簇号
|
||||||
|
next_clustno = clustno + 1;
|
||||||
|
while (1) {
|
||||||
|
if (*(fat1 + next_clustno) == 0) {
|
||||||
|
*(fat1 + clustno) = next_clustno;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
next_clustno++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clustno = next_clustno;
|
||||||
|
}
|
||||||
|
next_clustno = *(fat1 + clustno);
|
||||||
|
*(fat1 + clustno) = 0xffff; //0xfff8~0xffff表示文件结束,没有下一个簇了。
|
||||||
|
//如果本次写入的内容比上次的少,上次用过的簇号本次用不完,以下将剩下的簇号清零处理。
|
||||||
|
if (1 < next_clustno && next_clustno < 0xfff0) {
|
||||||
|
while (1) {
|
||||||
|
clustno = next_clustno;
|
||||||
|
next_clustno = *(fat1 + clustno);
|
||||||
|
*(fat1 + clustno) = 0;
|
||||||
|
if (next_clustno >= 0xfff8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alter_dir_entry(file);
|
||||||
|
save_fat1(fat1);
|
||||||
|
kfree(fat1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_file(struct File *file) {
|
||||||
|
//1.标记目录项为已删除。
|
||||||
|
struct File *root_entries = kmalloc(SECTOR_SIZE);
|
||||||
|
read_root_dir_sector1(root_entries);
|
||||||
|
for (int i = 0; i < MAX_FILE_NUM; i++) {
|
||||||
|
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
|
||||||
|
root_entries[i].name[0] = 0xe5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save_root_dir_sector1(root_entries);
|
||||||
|
kfree(root_entries);
|
||||||
|
if (file->clustno == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
|
||||||
|
get_fat1(fat1);
|
||||||
|
unsigned short clustno = file->clustno;
|
||||||
|
unsigned short next_clustno = 0;
|
||||||
|
while (1) {
|
||||||
|
next_clustno = *(fat1 + clustno);
|
||||||
|
*(fat1 + clustno) = 0;
|
||||||
|
if (next_clustno >= 0xfff8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
clustno = next_clustno;
|
||||||
|
}
|
||||||
|
save_fat1(fat1);
|
||||||
|
kfree(fat1);
|
||||||
|
}
|
64
kernel/gdt.c
Normal file
64
kernel/gdt.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "../include/description_table.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
extern void tss_flush();
|
||||||
|
extern uint32_t stack;
|
||||||
|
|
||||||
|
gdt_entry_t gdt_entries[GDT_LENGTH];
|
||||||
|
gdt_ptr_t gdt_ptr;
|
||||||
|
tss_entry tss;
|
||||||
|
|
||||||
|
void gdt_set_gate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||||
|
gdt_entries[num].base_low = (base & 0xFFFF);
|
||||||
|
gdt_entries[num].base_middle = (base >> 16) & 0xFF;
|
||||||
|
gdt_entries[num].base_high = (base >> 24) & 0xFF;
|
||||||
|
|
||||||
|
gdt_entries[num].limit_low = (limit & 0xFFFF);
|
||||||
|
gdt_entries[num].granularity = (limit >> 16) & 0x0F;
|
||||||
|
|
||||||
|
gdt_entries[num].granularity |= gran & 0xF0;
|
||||||
|
gdt_entries[num].access = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_tss(int32_t num, uint16_t ss0, uint32_t esp0) {
|
||||||
|
uintptr_t base = (uintptr_t) & tss;
|
||||||
|
uintptr_t limit = base + sizeof(tss);
|
||||||
|
|
||||||
|
gdt_set_gate(num, base, limit, 0xE9, 0x00);
|
||||||
|
|
||||||
|
memset((uint8_t * ) & tss, 0x0, sizeof(tss));
|
||||||
|
|
||||||
|
tss.ss0 = ss0;
|
||||||
|
tss.esp0 = esp0;
|
||||||
|
tss.cs = 0x0b;
|
||||||
|
tss.ss = 0x13;
|
||||||
|
tss.ds = 0x13;
|
||||||
|
tss.es = 0x13;
|
||||||
|
tss.fs = 0x13;
|
||||||
|
tss.gs = 0x13;
|
||||||
|
|
||||||
|
tss.iomap_base = sizeof(tss);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_kernel_stack(uintptr_t stack) {
|
||||||
|
tss.esp0 = stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdt_install() {
|
||||||
|
gdt_ptr.limit = sizeof(gdt_entry_t) * GDT_LENGTH - 1;
|
||||||
|
gdt_ptr.base = (uint32_t)&gdt_entries;
|
||||||
|
|
||||||
|
gdt_set_gate(0, 0, 0, 0, 0); // 按照 Intel 文档要求,第一个描述符必须全 0
|
||||||
|
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // 指令段
|
||||||
|
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // 数据段
|
||||||
|
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // 用户模式代码段
|
||||||
|
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // 用户模式数据段
|
||||||
|
|
||||||
|
gdt_flush((uint32_t)&gdt_ptr);
|
||||||
|
|
||||||
|
write_tss(5, 0x10, 0x0);
|
||||||
|
tss_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
117
kernel/idt.c
Normal file
117
kernel/idt.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include "../include/description_table.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
#include "../include/isr.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
|
||||||
|
static isr_t interrupt_handlers[256];
|
||||||
|
idt_entry_t idt_entries[256]; // IDT有256个描述符
|
||||||
|
idt_ptr_t idt_ptr;
|
||||||
|
|
||||||
|
extern void idt_flush(uint32_t);
|
||||||
|
|
||||||
|
static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) {
|
||||||
|
idt_entries[num].base_low = base & 0xFFFF;
|
||||||
|
idt_entries[num].base_high = (base >> 16) & 0xFFFF; // 拆成低位和高位
|
||||||
|
|
||||||
|
idt_entries[num].sel = sel;
|
||||||
|
idt_entries[num].always0 = 0;
|
||||||
|
idt_entries[num].flags = flags;
|
||||||
|
// flags | 0x60,即可被Ring3调用
|
||||||
|
}
|
||||||
|
|
||||||
|
void isr_handler(registers_t regs) {
|
||||||
|
printf("\n[Kernel]: received interrupt: %d",regs.int_no);
|
||||||
|
|
||||||
|
if (interrupt_handlers[regs.int_no]) {
|
||||||
|
isr_t handler = interrupt_handlers[regs.int_no]; // 有自定义处理程序,调用之
|
||||||
|
handler(®s); // 传入寄存器
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void irq_handler(registers_t regs) {
|
||||||
|
if (regs.int_no >= 40) outb(0xA0, 0x20); // 中断号 >= 40,来自从片,发送EOI给从片
|
||||||
|
outb(0x20, 0x20); // 发送EOI给主片
|
||||||
|
|
||||||
|
if (interrupt_handlers[regs.int_no]) {
|
||||||
|
isr_t handler = interrupt_handlers[regs.int_no]; // 有自定义处理程序,调用之
|
||||||
|
handler(®s); // 传入寄存器
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_interrupt_handler(uint8_t n, isr_t handler) {
|
||||||
|
interrupt_handlers[n] = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void idt_install() {
|
||||||
|
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
|
||||||
|
idt_ptr.base = (uint32_t) & idt_entries;
|
||||||
|
|
||||||
|
memset(&idt_entries, 0, sizeof(idt_entry_t) * 256);
|
||||||
|
|
||||||
|
outb(0x20, 0x11);
|
||||||
|
outb(0xA0, 0x11);
|
||||||
|
outb(0x21, 0x20);
|
||||||
|
outb(0xA1, 0x28);
|
||||||
|
outb(0x21, 0x04);
|
||||||
|
outb(0xA1, 0x02);
|
||||||
|
outb(0x21, 0x01);
|
||||||
|
outb(0xA1, 0x01);
|
||||||
|
outb(0x21, 0x0);
|
||||||
|
outb(0xA1, 0x0);
|
||||||
|
|
||||||
|
|
||||||
|
#define REGISTER_ISR(id) idt_set_gate(id, (uint32_t) isr##id, 0x08, 0x8E)
|
||||||
|
REGISTER_ISR(0);
|
||||||
|
REGISTER_ISR(1);
|
||||||
|
REGISTER_ISR(2);
|
||||||
|
REGISTER_ISR(3);
|
||||||
|
REGISTER_ISR(4);
|
||||||
|
REGISTER_ISR(5);
|
||||||
|
REGISTER_ISR(6);
|
||||||
|
REGISTER_ISR(7);
|
||||||
|
REGISTER_ISR(8);
|
||||||
|
REGISTER_ISR(9);
|
||||||
|
REGISTER_ISR(10);
|
||||||
|
REGISTER_ISR(11);
|
||||||
|
REGISTER_ISR(12);
|
||||||
|
REGISTER_ISR(13);
|
||||||
|
REGISTER_ISR(14);
|
||||||
|
REGISTER_ISR(15);
|
||||||
|
REGISTER_ISR(16);
|
||||||
|
REGISTER_ISR(17);
|
||||||
|
REGISTER_ISR(18);
|
||||||
|
REGISTER_ISR(19);
|
||||||
|
REGISTER_ISR(20);
|
||||||
|
REGISTER_ISR(21);
|
||||||
|
REGISTER_ISR(22);
|
||||||
|
REGISTER_ISR(23);
|
||||||
|
REGISTER_ISR(24);
|
||||||
|
REGISTER_ISR(25);
|
||||||
|
REGISTER_ISR(26);
|
||||||
|
REGISTER_ISR(27);
|
||||||
|
REGISTER_ISR(28);
|
||||||
|
REGISTER_ISR(29);
|
||||||
|
REGISTER_ISR(30);
|
||||||
|
REGISTER_ISR(31);
|
||||||
|
#undef REGISTER_ISR
|
||||||
|
#define REGISTER_IRQ(id, irq_id) idt_set_gate(id, (uint32_t) irq##irq_id, 0x08, 0x8E)
|
||||||
|
REGISTER_IRQ(32, 0);
|
||||||
|
REGISTER_IRQ(33, 1);
|
||||||
|
REGISTER_IRQ(34, 2);
|
||||||
|
REGISTER_IRQ(35, 3);
|
||||||
|
REGISTER_IRQ(36, 4);
|
||||||
|
REGISTER_IRQ(37, 5);
|
||||||
|
REGISTER_IRQ(38, 6);
|
||||||
|
REGISTER_IRQ(39, 7);
|
||||||
|
REGISTER_IRQ(40, 8);
|
||||||
|
REGISTER_IRQ(41, 9);
|
||||||
|
REGISTER_IRQ(42, 10);
|
||||||
|
REGISTER_IRQ(43, 11);
|
||||||
|
REGISTER_IRQ(44, 12);
|
||||||
|
REGISTER_IRQ(45, 13);
|
||||||
|
REGISTER_IRQ(46, 14);
|
||||||
|
REGISTER_IRQ(47, 15);
|
||||||
|
#undef REGISTER_IRQ
|
||||||
|
idt_flush((uint32_t) & idt_ptr);
|
||||||
|
}
|
42
kernel/kernel.c
Normal file
42
kernel/kernel.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "../include/common.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/description_table.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/timer.h"
|
||||||
|
#include "../include/task.h"
|
||||||
|
#include "../include/cmos.h"
|
||||||
|
#include "../include/keyboard.h"
|
||||||
|
#include "../include/shell.h"
|
||||||
|
|
||||||
|
extern uint32_t end;
|
||||||
|
uint32_t placement_address = (uint32_t) & end;
|
||||||
|
|
||||||
|
|
||||||
|
void kernel_main() {
|
||||||
|
io_cli();
|
||||||
|
vga_install();
|
||||||
|
printf("[kernel]: VGA driver load success!\n");
|
||||||
|
gdt_install();
|
||||||
|
idt_install();
|
||||||
|
printf("[kernel]: description table config success!\n");
|
||||||
|
init_timer(10);
|
||||||
|
init_page();
|
||||||
|
printf("[kernel]: page set success!\n");
|
||||||
|
init_sched();
|
||||||
|
printf("[kernel]: PCB load success!\n");
|
||||||
|
init_keyboard();
|
||||||
|
printf("[kernel]: Keyboard driver load success!\n");
|
||||||
|
print_cpu_id();
|
||||||
|
io_sti();
|
||||||
|
|
||||||
|
clock_sleep(25);
|
||||||
|
|
||||||
|
kernel_thread(setup_shell,NULL,"CPOS-Shell");
|
||||||
|
|
||||||
|
|
||||||
|
for (;;){
|
||||||
|
io_hlt();
|
||||||
|
clock_sleep(1);
|
||||||
|
}
|
||||||
|
}
|
108
kernel/kheap.c
Normal file
108
kernel/kheap.c
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "../include/memory.h"
|
||||||
|
|
||||||
|
header_t *head = NULL, *tail = NULL; // 内存块链表
|
||||||
|
extern page_directory_t *current_directory;
|
||||||
|
extern uint32_t end; // declared in linker.ld
|
||||||
|
static uint32_t placement_address = (uint32_t) &end;
|
||||||
|
void *program_break, *program_break_end;
|
||||||
|
|
||||||
|
static uint32_t kmalloc_int(uint32_t sz, uint32_t align, uint32_t *phys) {
|
||||||
|
if (program_break) {
|
||||||
|
// 有内存堆
|
||||||
|
void *addr = alloc(sz); // 直接malloc,align丢掉了
|
||||||
|
if (phys) {
|
||||||
|
// 需要物理地址,先找到对应页
|
||||||
|
page_t *page = get_page((uint32_t) addr, 0, current_directory);
|
||||||
|
*phys = page->frame * 0x1000 + ((uint32_t) addr & 0xfff);
|
||||||
|
}
|
||||||
|
return (uint32_t) addr;
|
||||||
|
}
|
||||||
|
if (align && (placement_address & 0x00000FFF)) {
|
||||||
|
placement_address &= 0xFFFFF000;
|
||||||
|
placement_address += 0x1000;
|
||||||
|
}
|
||||||
|
if (phys) *phys = placement_address;
|
||||||
|
uint32_t tmp = placement_address;
|
||||||
|
placement_address += sz;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t kmalloc_a(uint32_t size) {
|
||||||
|
return kmalloc_int(size, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t kmalloc_p(uint32_t size, uint32_t *phys) {
|
||||||
|
return kmalloc_int(size, 0, phys);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t kmalloc_ap(uint32_t size, uint32_t *phys) {
|
||||||
|
return kmalloc_int(size, 1, phys);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t kmalloc(uint32_t size) {
|
||||||
|
return kmalloc_int(size, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ksbrk(int incr) {
|
||||||
|
if (program_break == 0 || program_break + incr >= program_break_end) return (void *) -1;
|
||||||
|
|
||||||
|
void *prev_break = program_break;
|
||||||
|
program_break += incr;
|
||||||
|
return prev_break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 寻找一个符合条件的指定大小的空闲内存块
|
||||||
|
static header_t *get_free_block(uint32_t size) {
|
||||||
|
header_t *curr = head;
|
||||||
|
while (curr) {
|
||||||
|
if (curr->s.is_free && curr->s.size >= size) return curr;
|
||||||
|
curr = curr->s.next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *alloc(uint32_t size) {
|
||||||
|
uint32_t total_size;
|
||||||
|
void *block;
|
||||||
|
header_t *header;
|
||||||
|
if (!size) return NULL;
|
||||||
|
header = get_free_block(size);
|
||||||
|
if (header) {
|
||||||
|
header->s.is_free = 0;
|
||||||
|
return (void *) (header + 1);
|
||||||
|
}
|
||||||
|
total_size = sizeof(header_t) + size;
|
||||||
|
block = ksbrk(total_size);
|
||||||
|
if (block == (void *) -1) return NULL;
|
||||||
|
header = block;
|
||||||
|
header->s.size = size;
|
||||||
|
header->s.is_free = 0;
|
||||||
|
header->s.next = NULL;
|
||||||
|
if (!head) head = header;
|
||||||
|
if (tail) tail->s.next = header;
|
||||||
|
tail = header;
|
||||||
|
return (void *) (header + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kfree(void *block) {
|
||||||
|
header_t *header, *tmp;
|
||||||
|
if (!block) return;
|
||||||
|
header = (header_t *) block - 1;
|
||||||
|
|
||||||
|
if ((char *) block + header->s.size == program_break) {
|
||||||
|
if (head == tail) head = tail = NULL;
|
||||||
|
else {
|
||||||
|
tmp = head;
|
||||||
|
while (tmp) {
|
||||||
|
if (tmp->s.next == tail) {
|
||||||
|
tmp->s.next = NULL;
|
||||||
|
tail = tmp;
|
||||||
|
}
|
||||||
|
tmp = tmp->s.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksbrk(0 - sizeof(header_t) - header->s.size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
header->s.is_free = 1;
|
||||||
|
}
|
44
kernel/memory.c
Normal file
44
kernel/memory.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "../include/memory.h"
|
||||||
|
|
||||||
|
|
||||||
|
void *memcpy(void *dst_, const void *src_, uint32_t size) {
|
||||||
|
uint8_t *dst = dst_;
|
||||||
|
const uint8_t *src = src_;
|
||||||
|
while (size-- > 0) *dst++ = *src++;
|
||||||
|
return (void *) src_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void *a_, const void *b_, uint32_t size) {
|
||||||
|
const char *a = a_;
|
||||||
|
const char *b = b_;
|
||||||
|
while (size-- > 0) {
|
||||||
|
if (*a != *b) return *a > *b ? 1 : -1;
|
||||||
|
a++, b++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memset(void *s, int c, size_t n) {
|
||||||
|
unsigned char *p = s;
|
||||||
|
while (n-- > 0)
|
||||||
|
*p++ = c;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memmove(void *dest, const void *src, size_t num) {
|
||||||
|
void *ret = dest;
|
||||||
|
if (dest < src) {
|
||||||
|
while (num--)//前->后
|
||||||
|
{
|
||||||
|
*(char *) dest = *(char *) src;
|
||||||
|
dest = (char *) dest + 1;
|
||||||
|
src = (char *) src + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (num--)//后->前
|
||||||
|
{
|
||||||
|
*((char *) dest + num) = *((char *) src + num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
151
kernel/page.c
Normal file
151
kernel/page.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#include "../include/memory.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
|
||||||
|
page_directory_t *kernel_directory = 0; // 内核用页目录
|
||||||
|
page_directory_t *current_directory = 0; // 当前页目录
|
||||||
|
|
||||||
|
uint32_t *frames;
|
||||||
|
uint32_t nframes;
|
||||||
|
|
||||||
|
extern uint32_t placement_address;
|
||||||
|
extern void *program_break, *program_break_end;
|
||||||
|
|
||||||
|
static void set_frame(uint32_t frame_addr) {
|
||||||
|
uint32_t frame = frame_addr / 0x1000;
|
||||||
|
uint32_t idx = INDEX_FROM_BIT(frame);
|
||||||
|
uint32_t off = OFFSET_FROM_BIT(frame);
|
||||||
|
frames[idx] |= (0x1 << off);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_frame(uint32_t frame_addr) {
|
||||||
|
uint32_t frame = frame_addr / 0x1000;
|
||||||
|
uint32_t idx = INDEX_FROM_BIT(frame);
|
||||||
|
uint32_t off = OFFSET_FROM_BIT(frame);
|
||||||
|
frames[idx] &= ~(0x1 << off);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t test_frame(uint32_t frame_addr) {
|
||||||
|
uint32_t frame = frame_addr / 0x1000;
|
||||||
|
uint32_t idx = INDEX_FROM_BIT(frame);
|
||||||
|
uint32_t off = OFFSET_FROM_BIT(frame);
|
||||||
|
return (frames[idx] & (0x1 << off));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t first_frame() {
|
||||||
|
for (int i = 0; i < INDEX_FROM_BIT(nframes); i++) {
|
||||||
|
if (frames[i] != 0xffffffff) {
|
||||||
|
for (int j = 0; j < 32; j++) {
|
||||||
|
uint32_t toTest = 0x1 << j;
|
||||||
|
if (!(frames[i] & toTest)) {
|
||||||
|
return i * 4 * 8 + j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (uint32_t) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void alloc_frame(page_t *page, int is_kernel, int is_writable) {
|
||||||
|
if (page->frame) return;
|
||||||
|
else {
|
||||||
|
uint32_t idx = first_frame();
|
||||||
|
if (idx == (uint32_t) -1) {
|
||||||
|
printf("FRAMES_FREE_ERROR: Cannot free frames!\n");
|
||||||
|
asm("cli");
|
||||||
|
for (;;)io_hlt();
|
||||||
|
}
|
||||||
|
set_frame(idx * 0x1000);
|
||||||
|
page->present = 1; // 现在这个页存在了
|
||||||
|
page->rw = is_writable ? 1 : 0; // 是否可写由is_writable决定
|
||||||
|
page->user = is_kernel ? 0 : 1; // 是否为用户态由is_kernel决定
|
||||||
|
page->frame = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_frame(page_t *page) {
|
||||||
|
uint32_t frame = page->frame;
|
||||||
|
if (!frame) return;
|
||||||
|
else {
|
||||||
|
clear_frame(frame);
|
||||||
|
page->frame = 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void switch_page_directory(page_directory_t *dir) {
|
||||||
|
current_directory = dir;
|
||||||
|
asm volatile("mov %0, %%cr3" : : "r"(&dir->tablesPhysical));
|
||||||
|
uint32_t cr0;
|
||||||
|
asm volatile("mov %%cr0, %0" : "=r"(cr0));
|
||||||
|
cr0 |= 0x80000000;
|
||||||
|
asm volatile("mov %0, %%cr0" : : "r"(cr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
page_t *get_page(uint32_t address, int make, page_directory_t *dir) {
|
||||||
|
address /= 0x1000;
|
||||||
|
uint32_t table_idx = address / 1024;
|
||||||
|
if (dir->tables[table_idx]) return &dir->tables[table_idx]->pages[address % 1024];
|
||||||
|
else if (make) {
|
||||||
|
uint32_t tmp;
|
||||||
|
dir->tables[table_idx] = (page_table_t *) kmalloc_ap(sizeof(page_table_t), &tmp);
|
||||||
|
memset(dir->tables[table_idx], 0, 0x1000);
|
||||||
|
dir->tablesPhysical[table_idx] = tmp | 0x7;
|
||||||
|
return &dir->tables[table_idx]->pages[address % 1024];
|
||||||
|
} else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void page_fault(registers_t *regs) {
|
||||||
|
asm("cli");
|
||||||
|
uint32_t faulting_address;
|
||||||
|
asm volatile("mov %%cr2, %0" : "=r" (faulting_address)); //
|
||||||
|
|
||||||
|
int present = !(regs->err_code & 0x1); // 页不存在
|
||||||
|
int rw = regs->err_code & 0x2; // 只读页被写入
|
||||||
|
int us = regs->err_code & 0x4; // 用户态写入内核页
|
||||||
|
int reserved = regs->err_code & 0x8; // 写入CPU保留位
|
||||||
|
int id = regs->err_code & 0x10; // 由取指引起
|
||||||
|
|
||||||
|
printf("[ERROR]: Page fault |");
|
||||||
|
if (present)
|
||||||
|
printf("Type: present;\n\taddress: %x ", faulting_address);
|
||||||
|
else if (rw)
|
||||||
|
printf("Type: read-only;\n\taddress: %x", faulting_address);
|
||||||
|
else if (us)
|
||||||
|
printf("Type: user-mode;\n\taddres: %x", faulting_address);
|
||||||
|
else if (reserved)
|
||||||
|
printf("Type: reserved;\n\taddress: %x", faulting_address);
|
||||||
|
else if (id)
|
||||||
|
printf("Type: decode address;\n\taddress: %x", faulting_address);
|
||||||
|
|
||||||
|
|
||||||
|
for (;;) io_hlt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_page() {
|
||||||
|
uint32_t mem_end_page = 0xFFFFFFFF; // 4GB Page
|
||||||
|
|
||||||
|
nframes = mem_end_page / 0x1000;
|
||||||
|
frames = (uint32_t *) kmalloc(INDEX_FROM_BIT(nframes));
|
||||||
|
memset(frames, 0, INDEX_FROM_BIT(nframes));
|
||||||
|
|
||||||
|
kernel_directory = (page_directory_t *) kmalloc_a(sizeof(page_directory_t)); //kmalloc: 无分页情况自动在内核后方分配 | 有分页从内核堆分配
|
||||||
|
|
||||||
|
memset(kernel_directory, 0, sizeof(page_directory_t));
|
||||||
|
current_directory = kernel_directory;
|
||||||
|
int i = 0;
|
||||||
|
while (i < placement_address) {
|
||||||
|
// 内核部分对ring3而言可读不可写 | 无偏移页表映射
|
||||||
|
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||||
|
i += 0x1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i++) {
|
||||||
|
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
register_interrupt_handler(14, page_fault);
|
||||||
|
switch_page_directory(kernel_directory);
|
||||||
|
|
||||||
|
program_break = (void *) KHEAP_START;
|
||||||
|
program_break_end = (void *) (KHEAP_START + KHEAP_INITIAL_SIZE);
|
||||||
|
}
|
129
kernel/task.c
Normal file
129
kernel/task.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include "../include/task.h"
|
||||||
|
#include "../include/common.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
|
||||||
|
struct task_struct *running_proc_head = NULL;
|
||||||
|
struct task_struct *wait_proc_head = NULL;
|
||||||
|
struct task_struct *current = NULL;
|
||||||
|
|
||||||
|
extern void switch_to(struct context *prev, struct context *next);
|
||||||
|
|
||||||
|
int now_pid = 0;
|
||||||
|
|
||||||
|
void print_proc_t(int *i,struct task_struct *base,struct task_struct *cur){
|
||||||
|
if(cur->pid == base->pid){
|
||||||
|
switch (cur->state) {
|
||||||
|
case TASK_RUNNABLE:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Running");
|
||||||
|
break;
|
||||||
|
case TASK_SLEEPING:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Sleeping");
|
||||||
|
break;
|
||||||
|
case TASK_UNINIT:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Init");
|
||||||
|
break;
|
||||||
|
case TASK_ZOMBIE:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Zombie");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(*i)++;
|
||||||
|
} else{
|
||||||
|
switch (cur->state) {
|
||||||
|
case TASK_RUNNABLE:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Running");
|
||||||
|
break;
|
||||||
|
case TASK_SLEEPING:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Sleeping");
|
||||||
|
break;
|
||||||
|
case TASK_UNINIT:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Init");
|
||||||
|
break;
|
||||||
|
case TASK_ZOMBIE:
|
||||||
|
printf("%s %d %s\n",cur->name,cur->pid,"Zombie");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(*i)++;
|
||||||
|
print_proc_t(i,base,cur->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_proc(){
|
||||||
|
printf("====--------[Processes]---------===\n");
|
||||||
|
int index = 0;
|
||||||
|
print_proc_t(&index,current,current->next);
|
||||||
|
printf("Name Pid Status [All Proc: %d]\n\n",index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void schedule() {
|
||||||
|
if (current) {
|
||||||
|
change_task_to(current->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void change_task_to(struct task_struct *next) {
|
||||||
|
if (current != next) {
|
||||||
|
struct task_struct *prev = current;
|
||||||
|
current = next;
|
||||||
|
switch_to(&(prev->context), &(current->context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t kernel_thread(int (*fn)(void *), void *arg,char* name) {
|
||||||
|
struct task_struct *new_task = (struct task_struct *) kmalloc(STACK_SIZE);
|
||||||
|
assert(new_task != NULL, "kern_thread: kmalloc error");
|
||||||
|
|
||||||
|
// 将栈低端结构信息初始化为 0
|
||||||
|
memset(new_task,0, sizeof(struct task_struct));
|
||||||
|
|
||||||
|
new_task->state = TASK_RUNNABLE;
|
||||||
|
new_task->stack = current;
|
||||||
|
new_task->pid = now_pid++;
|
||||||
|
new_task->mm = NULL;
|
||||||
|
new_task->name = name;
|
||||||
|
|
||||||
|
uint32_t *stack_top = (uint32_t * )((uint32_t) new_task + STACK_SIZE);
|
||||||
|
|
||||||
|
*(--stack_top) = (uint32_t) arg;
|
||||||
|
*(--stack_top) = (uint32_t) kthread_exit;
|
||||||
|
*(--stack_top) = (uint32_t) fn;
|
||||||
|
|
||||||
|
new_task->context.esp = (uint32_t) new_task + STACK_SIZE - sizeof(uint32_t) * 3;
|
||||||
|
|
||||||
|
// 设置新任务的标志寄存器未屏蔽中断,很重要
|
||||||
|
new_task->context.eflags = 0x200;
|
||||||
|
new_task->next = running_proc_head;
|
||||||
|
|
||||||
|
// 找到当前进任务队列,插入到末尾
|
||||||
|
struct task_struct *tail = running_proc_head;
|
||||||
|
assert(tail != NULL, "Must init sched!");
|
||||||
|
|
||||||
|
while (tail->next != running_proc_head) {
|
||||||
|
tail = tail->next;
|
||||||
|
}
|
||||||
|
tail->next = new_task;
|
||||||
|
|
||||||
|
return new_task->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kthread_exit() {
|
||||||
|
register uint32_t val asm ("eax");
|
||||||
|
|
||||||
|
printf("Thread exited with value %d\n", val);
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_sched() {
|
||||||
|
// 为当前执行流创建信息结构体 该结构位于当前执行流的栈最低端
|
||||||
|
current = (struct task_struct *) kmalloc(sizeof(struct task_struct));
|
||||||
|
|
||||||
|
current->state = TASK_RUNNABLE;
|
||||||
|
current->pid = now_pid++;
|
||||||
|
current->stack = current; // 该成员指向栈低地址
|
||||||
|
current->mm = NULL; // 内核线程不需要该成员
|
||||||
|
current->name = "CPOS-System";
|
||||||
|
|
||||||
|
current->next = current;
|
||||||
|
|
||||||
|
running_proc_head = current;
|
||||||
|
}
|
35
kernel/timer.c
Normal file
35
kernel/timer.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "../include/timer.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/isr.h"
|
||||||
|
#include "../include/task.h"
|
||||||
|
|
||||||
|
uint32_t tick = 0;
|
||||||
|
|
||||||
|
static void timer_handle(registers_t *regs) {
|
||||||
|
io_cli();
|
||||||
|
tick++;
|
||||||
|
schedule();
|
||||||
|
io_sti();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clock_sleep(uint32_t timer){
|
||||||
|
uint32_t sleep = tick + timer;
|
||||||
|
while(1){
|
||||||
|
printf("");
|
||||||
|
if(tick >= sleep)break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_timer(uint32_t timer) {
|
||||||
|
register_interrupt_handler(IRQ0, &timer_handle);
|
||||||
|
uint32_t divisor = 1193180 / timer;
|
||||||
|
|
||||||
|
outb(0x43, 0x36); // 频率
|
||||||
|
|
||||||
|
uint8_t l = (uint8_t) (divisor & 0xFF);
|
||||||
|
uint8_t h = (uint8_t) ((divisor >> 8) & 0xFF);
|
||||||
|
|
||||||
|
outb(0x40, l);
|
||||||
|
outb(0x40, h);
|
||||||
|
}
|
34
linker.ld
Normal file
34
linker.ld
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
|
||||||
|
. = 2M;
|
||||||
|
|
||||||
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
code = .; _code = .; __code = .;
|
||||||
|
*(.multiboot)
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
data = .; _data = .; __data = .;
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
bss = .; _bss = .; __bss = .;
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
end = .; _end = .; __end = .;
|
||||||
|
}
|
217
sysapp/shell.c
Normal file
217
sysapp/shell.c
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
#include "../include/shell.h"
|
||||||
|
#include "../include/queue.h"
|
||||||
|
#include "../include/vga.h"
|
||||||
|
#include "../include/common.h"
|
||||||
|
#include "../include/io.h"
|
||||||
|
#include "../include/task.h"
|
||||||
|
#include "../include/cmos.h"
|
||||||
|
#include "../include/fat16.h"
|
||||||
|
|
||||||
|
extern Queue *key_char_queue;
|
||||||
|
|
||||||
|
char getc() {
|
||||||
|
while (key_char_queue->size == 0x00) {
|
||||||
|
io_hlt();
|
||||||
|
|
||||||
|
}
|
||||||
|
return queue_pop(key_char_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gets(char *buf, int buf_size) {
|
||||||
|
int index = 0;
|
||||||
|
char c;
|
||||||
|
while ((c = getc()) != '\n') {
|
||||||
|
if (c == '\b') {
|
||||||
|
if (index > 0) {
|
||||||
|
index--;
|
||||||
|
vga_writestring("\b \b");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buf[index++] = c;
|
||||||
|
vga_putchar(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[index] = '\0';
|
||||||
|
vga_putchar(c);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_parse(char *cmd_str, char **argv, char token) {
|
||||||
|
int arg_idx = 0;
|
||||||
|
while (arg_idx < MAX_ARG_NR) {
|
||||||
|
argv[arg_idx] = NULL;
|
||||||
|
arg_idx++;
|
||||||
|
}
|
||||||
|
char *next = cmd_str;
|
||||||
|
int argc = 0;
|
||||||
|
|
||||||
|
while (*next) {
|
||||||
|
while (*next == token) *next++;
|
||||||
|
if (*next == 0) break;
|
||||||
|
argv[argc] = next;
|
||||||
|
while (*next && *next != token) *next++;
|
||||||
|
if (*next) *next++ = 0;
|
||||||
|
if (argc > MAX_ARG_NR) return -1;
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_echo(int argc, char **argv) {
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (i == 1) vga_writestring("");
|
||||||
|
else vga_writestring(" ");
|
||||||
|
vga_writestring(argv[i]);
|
||||||
|
}
|
||||||
|
vga_putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_proc(){
|
||||||
|
print_proc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_date(){
|
||||||
|
printf("System Time: %s\n",get_date_time());
|
||||||
|
print_cpu_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_ls() {
|
||||||
|
struct File *root = (struct File *) kmalloc(sizeof(struct File) * MAX_FILE_NUM);
|
||||||
|
int files = read_root_dir(root);
|
||||||
|
int index = 0, size = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < files; ++i) {
|
||||||
|
struct File file = root[i];
|
||||||
|
if (!strcmp(file.name, "\0")) continue;
|
||||||
|
printf("%s %s %d\n", file.name, file.type == 0x20 ? "<FILE>" : " <DIR> ", file.size);
|
||||||
|
index++;
|
||||||
|
size += file.size;
|
||||||
|
}
|
||||||
|
printf(" All File: %d | All Size: %dByte\n", index, size);
|
||||||
|
kfree(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_cat(int argc, char **argv) {
|
||||||
|
if (argc <= 2) {
|
||||||
|
printf("[Shell-CAT]: If there are too few parameters, please specify the filename and data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct File *file = open_file(argv[1]);
|
||||||
|
if (file == NULL) {
|
||||||
|
printf("[Shell-CAT]: Not found [%s] \n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buffer[1024] = {0};
|
||||||
|
|
||||||
|
for (int i = 2; i < argc; i++) {
|
||||||
|
if (i == 2) strcat(buffer, "");
|
||||||
|
else strcat(buffer, " ");
|
||||||
|
strcat(buffer, argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
save_file(file, buffer);
|
||||||
|
kfree(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_read(int argc, char **argv) {
|
||||||
|
if (argc == 1) {
|
||||||
|
printf("[Shell-READ]: If there are too few parameters, please specify the filename");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct File *file = open_file(argv[1]);
|
||||||
|
char *buffer = (char *) kmalloc(sizeof(char) * 4096);
|
||||||
|
if (file == NULL) {
|
||||||
|
printf("[Shell-READ]: Not found [%s] \n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_file(file, buffer);
|
||||||
|
printf("%s\n", buffer);
|
||||||
|
kfree(buffer);
|
||||||
|
kfree(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_mkdir(int argc, char **argv) {
|
||||||
|
if (argc == 1) {
|
||||||
|
printf("[Shell-MKDIR]: If there are too few parameters, please specify the directory name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("Create directory: %s\n",argv[1]);
|
||||||
|
struct File *dir = create_dir(argv[1]);
|
||||||
|
if (dir == NULL) {
|
||||||
|
printf("[Shell-MKDIR]: Cannot create directory '%s'.", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
kfree(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_del(int argc, char **argv) {
|
||||||
|
if (argc == 1) {
|
||||||
|
vga_writestring("[Shell-DEL]: If there are too few parameters, please specify the folder name.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct File *info = open_file(argv[1]);
|
||||||
|
if (info == NULL) {
|
||||||
|
printf("[Shell-DEL]: Not found [%s] \n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete_file(info);
|
||||||
|
kfree(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_shell(){
|
||||||
|
vga_clear();
|
||||||
|
printf("%s for x86 [Version %s] \n",OS_NAME, OS_VERSION);
|
||||||
|
printf("Copyright 2024 XIAOYI12 (Build by GCC i686-elf-tools)\n");
|
||||||
|
|
||||||
|
char com[MAX_COMMAND_LEN];
|
||||||
|
char *argv[MAX_ARG_NR];
|
||||||
|
int argc = -1;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
printf("CPOS/> ");
|
||||||
|
if (gets(com, MAX_COMMAND_LEN) <= 0) continue;
|
||||||
|
argc = cmd_parse(com, argv, ' ');
|
||||||
|
|
||||||
|
if (argc == -1) {
|
||||||
|
vga_writestring("[Shell]: Error: out of arguments buffer\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp("version", argv[0]))
|
||||||
|
printf("%s for x86 [%s]\n",OS_NAME, OS_VERSION);
|
||||||
|
else if (!strcmp("echo", argv[0]))
|
||||||
|
cmd_echo(argc, argv);
|
||||||
|
else if (!strcmp("clear", argv[0]))
|
||||||
|
vga_clear();
|
||||||
|
else if (!strcmp("proc", argv[0]))
|
||||||
|
cmd_proc();
|
||||||
|
else if (!strcmp("sysinfo", argv[0]))
|
||||||
|
cmd_date();
|
||||||
|
else if (!strcmp("ls", argv[0]))
|
||||||
|
cmd_ls();
|
||||||
|
else if (!strcmp("cat", argv[0]))
|
||||||
|
cmd_cat(argc, argv);
|
||||||
|
else if (!strcmp("read", argv[0]))
|
||||||
|
cmd_read(argc, argv);
|
||||||
|
else if (!strcmp("mkdir", argv[0]))
|
||||||
|
cmd_mkdir(argc, argv);
|
||||||
|
else if (!strcmp("del", argv[0]) || !strcmp("rm", argv[0]))
|
||||||
|
cmd_del(argc, argv);
|
||||||
|
else if (!strcmp("help", argv[0]) || !strcmp("?", argv[0]) || !strcmp("h", argv[0])) {
|
||||||
|
vga_writestring("-=[CrashPowerShell Helper]=-\n");
|
||||||
|
vga_writestring("help ? h Print shell help info.\n");
|
||||||
|
vga_writestring("version Print os version.\n");
|
||||||
|
vga_writestring("echo <msg> Print message.\n");
|
||||||
|
vga_writestring("ls List all files.\n");
|
||||||
|
vga_writestring("cat <name> <data> Edit a file\n");
|
||||||
|
vga_writestring("read <name> Read a file\n");
|
||||||
|
vga_writestring("mkdir <name> Make a directory\n");
|
||||||
|
vga_writestring("del rm <name> Delete a file\n");
|
||||||
|
vga_writestring("sysinfo Print system info.\n");
|
||||||
|
vga_writestring("proc Lists all running processes.\n");
|
||||||
|
} else printf("[Shell]: Unknown command '%s'.\n", argv[0]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user