实现多进程

This commit is contained in:
xiaoyi1212 2024-04-09 23:46:56 +08:00
commit 62575faf43
37 changed files with 3352 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.vscode/
i686_elf_tools/
cmake-build-debug/
isodir/

33
boot/boot.asm Normal file
View 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
View 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
View 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
View 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

Binary file not shown.

58
data/queue.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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(&regs); // 传入寄存器
}
}
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(&regs); // 传入寄存器
}
}
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
View 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
View 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); // 直接mallocalign丢掉了
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
View 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
View 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
View 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
View 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
View 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
View 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]);
}
}