@@ -0,0 +1,96 @@
#ifndef TYPES_H
#define TYPES_H

typedef unsigned long Pointer;
typedef unsigned long size_t;
typedef long ssize_t;
typedef int pid_t;
typedef unsigned char Byte;
typedef int (*IrqHandler)(int);

typedef struct{
long back_link;
long esp0;
long ss0;
long esp1;
long ss1;
long esp2;
long ss2;
long cr3;
long eip;
long eflags;
long eax,ecx,edx,ebx;
long esp;
long ebp;
long esi;
long edi;
long es;
long cs;
long ss;
long ds;
long fs;
long gs;
long ldt;
long io;
}Tss;

typedef struct {
long gs;
long fs;
long ds;
long es;
long edi;
long esi;
long ebp;
long _esp;
long ebx;
long edx;
long ecx;
long eax;
long eip;
long cs;
long eflags;
long esp;
long ss;
}Registers;


typedef struct message Message;
struct message{
int type;
pid_t src;
union{
struct{Pointer cr2,cr3;};
char msg[64 - 8];
};
};
typedef struct intelink Interrput;
struct intelink{
Message message;
Interrput *next;
};
typedef struct proc Proc;
struct proc{
pid_t pid;
long counter;
long timeout;
int pri;
int flags;
pid_t getfrom,wait;
Pointer core;
Pointer esp0;
Registers *registers;
char pname[16];
Message message;
Interrput *interruptlink;
struct proc *next,*prev;
struct proc *sendlink;
};

union{
Proc proc;
char stack[KERNEL_STACK_SIZE];
}Task;


#endif
@@ -0,0 +1,60 @@
/*
* (c) LuoZH 2011
* 这个文件的目录好像很深的样子,这个文件主要就是定义几个供内核操作IO使用
* 的C语言宏,没有其他什么的.可以看出,我很多东西都抄linux的,这算不算抄?
* 额,差点忘了,这段引至linux,版权不归我所有,好吧,上面版权那行无效.希望linus
* 等人看到不会揍我,我是无辜的:-)
*/
#define outb(value,port) \
asm("out %%al,%%dx"::"a"(value),"d"(port))
#define outw(value,port) \
asm("out %%ax,%%dx"::"a"(value),"d"(port))
//下面这个其实我不是很理解,为何这样就能返回_v的值`
#define inb(port) ({\
unsigned char _v; \
asm volatile("in %%dx,%%al":"=a"(_v):"d"(port)); \
_v;\
})
#define inw(port) ({\
unsigned short _v; \
asm volatile("in %%dx,%%ax":"=a"(_v):"d"(port)); \
_v;\
})
//下面是带延时功能的
#define outb_p(value,port) \
asm("out %%al,%%dx\n"\
"jmp 1f\n" \
"1:jmp 1f\n" \
"1:"::"a"(value),"d"(port) \
)
#define outw_p(value,port) \
asm("out %%ax,%%dx\n"\
"jmp 1f\n" \
"1:jmp 1f\n" \
"1:"::"a"(value),"d"(port) \
)
#define inb_p(port) ({\
unsigned char _v; \
asm volatile("in %%dx,%%al\n" \
"jmp 1f\n" \
"1:jmp 1f\n" \
"1:":"=a"(_v):"d"(port));\
_v; \
})
#define inw_p(port) ({\
unsigned short _v; \
asm volatile("in %%dx,%%al\n" \
"jmp 1f\n" \
"1:jmp 1f\n" \
"1:":"=a"(_v):"d"(port));\
_v; \
})

#define sti() asm("sti")
#define cli() asm("cli")
#define wait() asm("wait")
#define hlt() asm("hlt")
#define invalidate() \
asm("mov %%cr3,%%eax\n\t" \
"mov %%eax,%%cr3\n\t" \
:::"%eax")
@@ -0,0 +1,47 @@
# Makefile for all
#
.PHONY:clear install make all

# Directories
i = $r/include
s = none
l = $r/lib
m = $r/mm

#kernel entry
entry = 0x305000
vpath %.h $r/include/

# Programs, flags, etc.
AS = as
CC = gcc
LD = ld

ASFLAGS = --32
CFLAGS = -I $i -m32 -c -std=gnu99 -nostdinc -fno-stack-protector -Wall
LDFLAGS = -m elf_i386 -Ttext $(entry) -nostdlib \
-L $l -lc #--oformat binary

HEAD = stdio.h malloc.h stddef.h stdarg.h

OBJS = setup.o main.o console.o printk.o panic.o x86.o trap.o proc.o\
mm.o\
clock.o

LIBS = $l/libc.a
# What to make.
#
$s:$(OBJS) $(LIBS)
$(LD) $(OBJS) -o $@ $(LDFLAGS)

%.o:%.S
$(CC) $< -o $@ $(CFLAGS)

%.o:%.c
$(CC) $< -o $@ $(CFLAGS)

%.o:%.s
$(AS) $< -o $@ $(ASFLAGS)

clear:
-rm *.o -rf
@@ -0,0 +1,108 @@
#include "kernel.h"
#include <time.h>

volatile unsigned long jiffies = 0;
static time_t startup_time;
void unready(Proc *rp);
void pick_proc(void);


Registers *clock_handler(Registers *reg){
act_proc->registers = reg;
static Message m = {.type = HARD_INT};
if(!(jiffies % 10)) interrupt(CLOCK_PID,&m);
//if(act_proc != proc_ptr) printk("%s -> %s\n",act_proc->pname,proc_ptr->pname);
act_proc = proc_ptr;
tss->esp0 = act_proc->esp0;
ldcr3(act_proc->core);
return act_proc->registers;
}

#define CMOS_READ(addr) ({\
outb_p(0x80 | addr,0x70); \
inb_p(0x71);\
})

#define BCD_TO_BIN(val) ((val) = ((val) & 0xf) + ((val) >> 4)* 10)

#define MINUTE 60
#define HOUR (60 * MINUTE)
#define DAY (24 * HOUR)
#define YEAR (365 * DAY)

static time_t mktime(Time *tm){
time_t res;
static const int month[12] = {
0,
31,
31 + 28,
31 + 28 + 31,
31 + 28 + 31 + 30,
31 + 28 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
};

res = YEAR * (tm->year) + DAY * (tm->year + 3) / 4;
res += DAY * month[tm->month];
if(tm->month > 1 && (!(tm->year % 4)))
res += DAY;
res += DAY * (tm->day - 1);
res += HOUR * tm->hour;
res += MINUTE * tm->minute;
res += tm->second;
return res;
}

static Time *cmos_time(void){
static Time time;
do{
time.second = CMOS_READ(0);
time.minute = CMOS_READ(2);
time.hour = CMOS_READ(4);
time.day = CMOS_READ(7);
time.month = CMOS_READ(8);
time.year = CMOS_READ(9);
}while(time.second != CMOS_READ(0));
BCD_TO_BIN(time.second);
BCD_TO_BIN(time.minute);
BCD_TO_BIN(time.hour);
BCD_TO_BIN(time.day);
BCD_TO_BIN(time.month);
BCD_TO_BIN(time.year);
time.month--;
startup_time = mktime(&time);
return &time;
}
void clock_init(void){
put_irq_handler(0,(IrqHandler)clock_handler);
cmos_time();
outb_p(0x36,0x43);
outb_p(LATCH&0xff,0x40);
outb_p(LATCH>>8,0x40);
enable_irq(0);
}
int clock_main(void){
Message m;
Time *time;
time = cmos_time();

printk("Clock Task runing!\n");
clock_init();
while(1){
recvie(ANY,&m);
switch(m.type){
case HARD_INT:pick_proc();break;//printk("\erHARD_INT\ew\n");break;
case GET_TIME:printk("second:%d ",startup_time);printk("%d/%d/%d %d:%d:%d\n",
time->year + 2000,time->month + 1,time->day,time->hour,time->minute,time->second);break;
}
}
unready(act_proc);
printk("\eW\eoError:clock is unready!\n\eO\ew");
while(1);
return 0;
}
BIN +3.3 KB kernel/clock.o
Binary file not shown.
@@ -0,0 +1,196 @@


#include "vga.h"

#define MAX_CONSOLES 1






static unsigned long video_mem_base; /* base of video memory */
static unsigned long video_num_columns; /* Number of text columns */
static unsigned long video_num_lines; /* NUmber of text lines */
static unsigned long video_size_row; /* Byte per row */
static int fg_cons; /* */

struct {
unsigned char attr; /* char attrib */
unsigned char def_attr; /* default attrib */
unsigned short erase_char; /* erase char and attrib */
unsigned long mem_start; /* memory start */
unsigned long mem_end; /* memory end */
unsigned long top; /* screen top */
unsigned long bottom; /* screen bottom */
unsigned long pos; /* cursor position */
unsigned int state;
}vc_cons[MAX_CONSOLES];


/* The maco consult Linus */

#define attr vc_cons[cons].attr
#define def_attr vc_cons[cons].def_attr
#define erase_char vc_cons[cons].erase_char
#define mem_start vc_cons[cons].mem_start
#define mem_end vc_cons[cons].mem_end
#define top vc_cons[cons].top
#define bottom vc_cons[cons].bottom
#define pos vc_cons[cons].pos
#define state vc_cons[cons].state


static inline void set_top(int cons){

//cli();
if(cons != fg_cons) return;
mc6845_write((0xff&(top - video_mem_base)>>9),START_ADDR_H);
mc6845_write(0xff&((top - video_mem_base)>>1),START_ADDR_L);
//sti();

}

static inline void set_cur(int cons){

//cli();
if(cons != fg_cons) return;
mc6845_write(0xff&((pos - video_mem_base)>>9),CURSOR_H);
mc6845_write(0xff&((pos - video_mem_base)>>1),CURSOR_L);
//sti();

}


static inline void scrup(int cons){

top += video_size_row;
bottom += video_size_row;
//pos += video_size_row;

if(bottom > mem_end){
__asm__ __volatile__("rep movsl\n\t\t"
"movl video_num_columns,%%ecx\n\t\t"
"rep stosw\n\t\t"
::"c"(((video_num_lines - 1)*(video_size_row))>>2),
"D"(mem_start),"S"(top),"a"(erase_char)
);
bottom -= top - mem_start;
pos -=top - mem_start;
top = mem_start;
}else{
__asm__ __volatile__("rep stosw\n\t\t"
::"D"(bottom),"c"(video_num_columns),"a"(erase_char));
}

set_top(cons);
//set_cur(cons);
}

static inline void scrdown(int cons){
if(top - video_size_row <= mem_start) return;
top -= video_size_row;
bottom -= video_size_row;
pos -= video_size_row;

set_top(cons);
set_cur(cons);
}

static inline void lf(int cons){

if(pos + video_size_row > bottom) scrup(cons);
pos += video_size_row;
set_cur(cons);
}

static inline void cr(int cons){
pos -= (pos - mem_start) % video_size_row;
set_cur(cons);
}

static inline void ri(int cons){
if(pos - video_size_row < top) scrdown(cons);
pos -= video_size_row;
set_cur(cons);
}

static inline void set_attr(int cons,unsigned char _attr){
attr = _attr;
}

static inline void del(int cons){
if((pos - mem_start)% video_size_row){
pos -= 2;
*(unsigned short *)pos = erase_char;
}
}


static inline void insert(int cons,unsigned char ch){

*(unsigned short *)pos = ch|(attr<<8);
if(pos + 2 > bottom){
scrup(cons);
}
pos += 2;
set_cur(cons);
}

extern void cons_print(int cons,const char * buf){

unsigned char ch;

while((ch = (*buf++))){
if(state == 1){
switch(ch){
case 'o':attr = (attr & 0xf0) | 0x00;break;
case 'O':attr = (attr & 0x0f) | 0x00;break;
case 'b':attr = (attr & 0xf0) | 0x01;break;
case 'B':attr = (attr & 0x0f) | 0x10;break;
case 'g':attr = (attr & 0xf0) | 0x02;break;
case 'G':attr = (attr & 0x0f) | 0x20;break;
case 'y':attr = (attr & 0xf0) | 0x03;break;
case 'Y':attr = (attr & 0x0f) | 0x30;break;
case 'r':attr = (attr & 0xf0) | 0x04;break;
case 'R':attr = (attr & 0x0f) | 0x40;break;
case 'p':attr = (attr & 0xf0) | 0x05;break;
case 'P':attr = (attr & 0x0f) | 0x50;break;
case 'h':attr = (attr & 0xf0) | 0x06;break;
case 'H':attr = (attr & 0x0f) | 0x60;break;
case 'w':attr = (attr & 0xf0) | 0x07;break;
case 'W':attr = (attr & 0x0f) | 0x70;break;
}
state = 0;
}
else if(ch == '\e') state = 1;
else if(ch == '\n'){
lf(cons);
cr(cons);
}else{
insert(cons,ch);
}
}
}

extern void cons_init(void){

int cons = 0;

fg_cons = 0;
video_mem_base = 0xb8000;
video_num_lines = 25;
video_num_columns = 80;
video_size_row = video_num_columns << 1;

attr = 0xf;
state = 0;
erase_char = ' ' | 0xf<<8;

mem_start = video_mem_base;
mem_end = mem_start + 80*25*2*3;
top = ((mc6845_read(START_ADDR_H)<<9)|(mc6845_read(START_ADDR_L)<<1)) + mem_start;
bottom = top + 80*25*2;
pos = ((mc6845_read(CURSOR_H)<<9)|(mc6845_read(CURSOR_L)<<1)) + mem_start;

}
BIN +6.21 KB kernel/console.o
Binary file not shown.
@@ -0,0 +1,9 @@
#ifndef __DRIVER_H__
#define __DRIVER_H__

typedef struct driver{
int dev;
int
};

#endif
@@ -0,0 +1,44 @@
#include <const.h>
#include <types.h>
#include <x86/io.h>
#include <sys/inter.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern void trap_init(void);
extern void mm_init(void);

/* */
extern void disable_irq(int irq);
extern void enable_irq(int irq);
extern void put_irq_handler(int irq,IrqHandler handler);

extern int interrupt(pid_t dest,Message *m_ptr);

extern void sched(void);

extern Proc *act_proc;
extern Proc *proc_ptr;
extern IrqHandler irq_table[NR_IRQ_VECTORS];

#define proc_number(rp) ((rp)->pid)
#define proc_addr(pid) (task[pid])

extern Tss *tss;

/* */
#define getcr3() ({ \
Pointer _cr3; \
asm("movl %%cr3,%0\n\t\t":"=a"(_cr3)); \
_cr3; \
})

#define ldcr3(cr3) ({\
asm("movl %0,%%cr3\n\t\t"::"a"(cr3));\
})

/* Task List */
int clock_main(void);


@@ -0,0 +1,16 @@
#include "kernel.h"

extern void cons_init();
extern int printk(const char *fmt,...);
extern void proc_init(void);
int main(void){

cli();
cons_init();
printk("\erHello \ebWorld!\n");
mm_init();
trap_init();
proc_init();
sti();
hlt();
}
BIN +1.19 KB kernel/main.o
Binary file not shown.
@@ -0,0 +1,94 @@
#include "kernel.h"
#include <multiboot.h>


#define clear_page(p) \
asm("rep stosl\n\t\t"::"a"(0),"c"(0x1000 >> 2),"D"(p));


Pointer MEMORY_END = 0;
Pointer MEMORY_MAP_END = 0;

unsigned char *mmap = (unsigned char *)MMAP_BASE;
/* get a free page in kernel space */
Pointer get_free_page(void){
while(1){
for(int i = CONST_MEM >> 12;i < KMEM >> 12;i++){
if(mmap[i] == 0){
mmap[i]++;
/* clear the page */
clear_page((i << 12));
return (i << 12);
}
}
}
return 0;
}

/* free a page in space */
void free_page(Pointer page){
if(page < CONST_MEM) panic("Free Kernel Memory!");
if(mmap[page >>12] == 0) panic("Free free Memory!");
mmap[page >>12] --;
}



void open_pagination(void){
Pointer *dir = (Pointer *)DIE_DIR;
Pointer *table = (Pointer *)DIE_TABLE;
Pointer page = 0;

memset((void *)dir,0,0x1000);
dir[0] = (Pointer)table | 7;
for(int i = 0;i < 1024;i++) table[i] = (i << 12) | 7;
for(int i = PAGE_OFFSET >> 22;i < (KMEM >> 22);i++){
table = (Pointer *)((Pointer)table + 0x1000);
dir[i] = (Pointer)table | 7;
for(int i = 0;i < 1024;i++) table[i] = ((page++) << 12) | 7;
}
table = (Pointer *)(dir[1023] & (~0xcff));
for(int i = 0;i < 1024;i++) table[i] = (1023 << 22) | (i << 12) | 7;

/* bios */
__asm__("mov %0,%%cr3\n\t\t"
"mov %%cr0,%%eax\n\t\t" "or $0x80010000,%%eax\n\t"
"mov %%eax,%%cr0\n\t\t"
::"a"(dir));

}




extern multiboot_info_t *envp;
void mm_init(void){

#define alow map->base_addr_low
#define ahigh map->base_addr_high
#define llow map->length_low
#define lhigh map->length_high
memory_map_t *map = (memory_map_t *)envp->mmap_addr;
memory_map_t *end = (memory_map_t *)(envp->mmap_addr + envp->mmap_length);

unsigned char busy = 100;

for(int i = 0;mmap + i < (unsigned char *)MMAP_END;i++) mmap[i] = 100;
for(;map < end;map++){
if(map->type == 1){
busy = 0;
MEMORY_END = alow + llow;
} else busy = 100;
for(Pointer i = alow >> 12;i < (alow + llow) >> 12;i++) mmap[i] = busy;
}
for(int i = 0;i < (CONST_MEM >> 12); i++) mmap[i] = 100;
if(MEMORY_END > KMEM ) MEMORY_MAP_END = KMEM;
else MEMORY_MAP_END = MEMORY_END;

open_pagination();
#undef alow
#undef ahigh
#undef llow
#undef lhigh
}

BIN +2.27 KB kernel/mm.o
Binary file not shown.
BIN +29.2 KB kernel/none
Binary file not shown.
@@ -0,0 +1,8 @@
#include "kernel.h"

extern void panic(const char *s){
printk("panic: %s\n",s);
cli();
while(1);
sti();
}
BIN +1.02 KB kernel/panic.o
Binary file not shown.
@@ -0,0 +1,18 @@
#include <stdarg.h>
#include <stddef.h>
#include "kernel.h"

extern void cons_print(int cons,const char *buf);

static char buf[1024];

extern int printk(const char *fmt,...){
va_list args;
int i;

va_start(args,fmt);
i=vsprintf(buf,fmt,args);
cons_print(0,buf);
return i;

}
BIN +1.07 KB kernel/printk.o
Binary file not shown.
@@ -0,0 +1,223 @@
#include "kernel.h"

#define istaskp(p) ((p)->pri == PRI_TASK)
#define isservep(p) ((p)->pri == PRI_SERVER)
#define isuserp(p) ((p)->pri == PRI_USER)
#define isnull(p) ((p) == NULL)

Proc *task[NR_TASKS];
Proc *act_proc;
Proc *proc_ptr;

Proc *rdy_head[NR_PRI];
Proc *rdy_tail[NR_PRI];

Tss *tss;

static int isrecv(pid_t src,pid_t dest){
if(src == ANY) return 1;
else return (src == dest);
}

void pick_proc(void){
//Proc *rp;
for(int i = 0;i < NR_PRI;i++){
if(NULL != rdy_head[i]){
proc_ptr = rdy_head[i];
return;
}
}
proc_ptr = proc_addr(IDLE);
}

void ready(Proc *rp){
if(isnull(rp)) panic("\erReady \eb[\erprocess is <null>\eb]");
if(isnull(rdy_head[rp->pri]))
rdy_head[rp->pri] = rp;
else
rdy_tail[rp->pri]->next = rp;
rp->next = NULL;
rdy_tail[rp->pri] = rp;
pick_proc();
}

void unready(Proc *rp){
Proc *xp;
if(isnull(rp)) panic("\erUnready \eb[\erprocess is <null>\eb]");
if(NULL == (xp = rdy_head[rp->pri])) return;
if(xp == rp){
rdy_head[rp->pri] = rp->next;
/*
if(rdy_tail[rp->pri] == rp)
rdy_tail[rp->pri] = NULL;
*/
}else{
while(xp->next != rp)
if(NULL == (xp = xp->next)) return;
xp->next = xp->next->next;
if(rdy_tail[rp->pri] == rp)
rdy_tail[rp->pri] = xp;
}
if(proc_ptr == rp) pick_proc();
hlt();
//while(act_proc == rp);
}

int proc_send(pid_t dest,Message *m_ptr){
Proc *rp,*sp;
sp = act_proc;
m_ptr->src = proc_number(sp);
if((rp = proc_addr(dest)) == NULL) return -1;
if((rp->flags & RECVIEING) && (rp->getfrom == proc_number(sp) || rp->getfrom == ANY )){
memcpy(&(rp->message),m_ptr,sizeof(Message));
rp->wait = m_ptr->src;
rp->flags &= ~(RECVIEING);
ready(rp);
unready(sp);
return 0;
}
Proc **sl;
sl = &rp->sendlink;
sp->sendlink = NULL;
memcpy(&(sp->message),m_ptr,sizeof(Message));
while(*sl != NULL) sl = &((*sl)->sendlink);
*sl = sp;
sp->flags |= SENDING;
unready(sp);
return 0;
}

int interrupt(pid_t dest,Message *m_ptr){
Proc *rp;
Interrput *inte;
m_ptr->src = HARDWORE;
if(NULL == (rp = proc_addr(dest))) panic("\erInterrupt \eb[\ersystem tasks don't found\eb]");
if((rp->flags & RECVIEING)){
memcpy(&(rp->message),m_ptr,sizeof(Message));
rp->wait = HARDWORE;
rp->flags &= ~(RECVIEING);
ready(rp);
return 0;
}
if(NULL == (inte = malloc(sizeof(Interrput)))) panic("\erInterrput \eb[\ermemory is out\eb]");
memcpy(&(inte->message),m_ptr,sizeof(Message));
inte->next = rp->interruptlink;
rp->interruptlink = inte;
return 0;
}

int proc_receive(pid_t src,Message *m_ptr){
Proc *rp,*np,**sp;
Interrput *inte;
rp = act_proc;
sp = &((rp)->sendlink);
np = rp->sendlink;

if((inte = rp->interruptlink)){
rp->interruptlink = inte->next;
memcpy(m_ptr,&(inte->message),sizeof(Message));
free(inte);
return 0;
}
while(np != NULL){
if(isrecv(src,proc_number(np))){
if((np->flags & SENDING)){
*sp = np->sendlink;
memcpy(m_ptr,&(np->message),sizeof(Message));
np->flags &= ~(SENDING);
ready(np);
return 0;
}
}
sp = &((*sp)->sendlink);
np = np->sendlink;
}
rp->flags |= RECVIEING;
rp->getfrom = src;
unready(rp);
memcpy(m_ptr,&(rp->message),sizeof(Message));
if(rp->wait != HARDWORE) ready(proc_addr(rp->wait));
return 0;
}

void sched(void){
if(rdy_head[PRI_USER] == NULL)return;

rdy_tail[PRI_USER]->next = rdy_head[PRI_USER];
rdy_tail[PRI_USER] = rdy_head[PRI_USER];
rdy_head[PRI_USER] = rdy_head[PRI_USER]->next;
rdy_tail[PRI_USER]->next = NULL;
pick_proc();
}

int system_main(void){
Message m;
m.type = GET_TIME;
send(CLOCK_PID,&m);
unready(act_proc);
while(1);
}

Proc *make_proc(pid_t pid,const char *pname,Pointer data,Pointer code,int pri,int (*pentry)()){
Proc *p;
p = (Proc*)get_free_page();
p->pid = pid;
p->pri = pri;
p->core = getcr3();
p->esp0 = (Pointer)p + sizeof(Task);
strcpy(p->pname,pname);
p->sendlink = NULL;
p->registers = (Registers*)(p->esp0 - 0x100);
p->interruptlink = NULL;
memcpy(p->registers,&(Registers){
.gs = data,
.fs = data,
.ds = data,
.es = data,
.edi = 0,
.esi = 0,
.ebp = 0,
.ebx = 0,
.edx = 0,
.ecx = 0,
.eax = 0,
.eip = (long)(pentry),
.cs = code,
.eflags = 0x200,
},sizeof(Registers));
task[pid] = p;
ready(p);
return p;
}

void proc_init(){

Pointer tr = TR_DESC;
Proc *idle;

for(int i = 0;i < NR_PRI;i++){
rdy_head[i] = rdy_tail[i] = NULL;
}
idle = (Proc *)get_free_page();
idle->pid = IDLE;
idle->core = getcr3();
idle->esp0 = (Pointer)(idle) + sizeof(Task);
strcpy(idle->pname,"idle");
idle->sendlink = NULL;
idle->interruptlink = NULL;
act_proc = idle;
task[IDLE] = idle;

make_proc(CLOCK_PID,"CLock",KERNEL_DATA,KERNEL_CODE,PRI_TASK,clock_main);
make_proc(SYSTEM_PID,"Sytem",KERNEL_DATA,KERNEL_CODE,PRI_TASK,system_main);

tss = (Tss*)(TSS_TABLE);
tss->ss0 = KERNEL_DATA;
tss->esp0 = idle->esp0;
//tss->gs = tss->fs = tss->es = tss->ds = USER_DATE;
tss->ldt = 0;
tss->io = 0xffff0000;
tss->eflags = 0x200;
asm("ltr %0"::"m"(tr));
pick_proc();
}
BIN +4.87 KB kernel/proc.o
Binary file not shown.
@@ -0,0 +1,167 @@
/*
* (C) 2011-10
* Email:LuoZhongYao@gmail.com
* 每天都对自己说:"Good luck!"
* 该程序负责初始化内核工作环境,是内核执行的第一个程序.
* 初始化内容包括,重新安排GDT(由multiboot规范知道,现在已经有一个GDT了),并且
* 对8259进行初始化,本质上来说,该程序只是原gmL的setup去除进入保护模式和添加
* multiboot支持而已.
* 使用multiboot的好处是可以使用现存的文件系统,而不用去研究它,可以被其
* 引导器引导.内核大小没有限制.反正很多啦,所以我个人建议,有写内核的同学,必
* 要参考multiboot,并遵守它.
*/
/* 汇编代码 */
#define ASM
/* multiboot规范头文件,该文件直接拷贝于grub_0.98/docs/multiboot.h */
#include <multiboot.h>
#include <const.h>

#define CreateSection(base,limit,attr) \
.short limit&0xffff;\
.short base&0xffff; \
.byte (base>>16)&0xff;\
.short (attr)|((limit>>8)&0x0f00);\
.byte (base>>24)&0xff;\
//代码段相关属性宏定义
#define CODE_READ 0x009a //代码段可读
#define CODE_C 0x009c //一致代码段
#define CODE_G 0x8098 //使用4GB的界限
#define CODE_D 0x4098 //默认使用32位地址
//数据段属性
#define DATA_WRITE 0x0092 //数据段可写
#define DATA_E 0x0094 //向下扩展
#define DATA_G 0x8090 //使用32界限
#define DATA_B 0x4090 //堆栈段使用ESP等32位指针,向下扩展,指明栈上限4GB
//TSS描述符
#define TSS_G 0x8089 //TSS使用4GB界限,通常这个是用不到的
#define TSS 0x0089 //说明这是一个TSS段
//权限
#define R0 0x0000 //ring 0
#define R1 0x0020 //
#define R2 0x0040 //
#define R3 0x0060 //ring 3
#define _STACK 0x3ffff0

GDT_LEN = gdt_end-gdt_start
/*
#define io_delay \
jmp .+2 \
jmp .+2
*/
/* IO延时宏 */
.macro io_delay
jmp .+2
jmp .+2
.endm
.text
.globl _start,envp,main
_start:
jmp start
/* multiboot 要求4字节对齐 */
.align 4
multiboot_header:
/* multiboot header magic 详情请查阅multiboot */
.long MULTIBOOT_HEADER_MAGIC
/* multiboot header flags multiboot为你做什么服务,色情服务不在这个范围内*/
/* 同时也告诉了multiboot你是什么款式的人,oh,程序 */
.long MULTIBOOT_HEADER_FLAGS
/* multiboot header checksum ,详情请看multiboot */
/* 我猜测引导器就是靠checksum和magic来识别multiboot header的. */
.long -(MULTIBOOT_HEADER_MAGIC+MULTIBOOT_HEADER_FLAGS)
/* 如果不是ELF文件格式,下面的信息就是必须的,这个__ELF__不知道是在哪里定义的 */
/* 不过我的二进制,就算下面这些提供了,grub还是不鸟我,所以我也不鸟二进制 */
#ifndef __ELF__
/* multiboot header addr,hi哥们,你在哪? */
.long multiboot_header
/* Load addr .text在OSimage中的偏移 */
.long _start
/* Load end addr 引导到OSimage中那个位置,如果为零,引导整个OS Image */
.long _edata
/* bss段的结束地址.Boot loader将其清零,并且保证不被覆盖 */
.long _end
/* Boot loader 引导完后将跳转到这里执行 */
.long _start
#endif
start:
cli
/*
mov $0x3FFFF0,%esp
push %ebx
*/
/* 保存由Boot loader提供的信息地址 */
mov %ebx,envp
/* 8259,写过很多次了,懒得在写,不懂的可以google,或者Email我 */
/* 唯一说一点的就是外部中断0x20~0x30 */
mov $0x11,%al
out %al,$0x20
io_delay
out %al,$0xa0
io_delay

mov $0x20,%al
out %al,$0x21
io_delay
mov $0x28,%al
out %al,$0xa1
io_delay

mov $0x04,%al
out %al,$0x21
io_delay
mov $0x2,%al
out %al,$0xa1
io_delay

mov $0x1,%al
out %al,$0x21
io_delay
out %al,$0xa1
io_delay

/* 屏蔽外部中断 */
mov $0xFF,%al
out %al,$0x21
io_delay
out %al,$0xa1
io_delay
/* 重新设置GDT,GDT被放置到0x101000处 */
mov $GDT_TABLE,%edi
mov $gdt_start,%esi
mov $GDT_LEN,%ecx
shr $2,%ecx
cld
rep movsl
lgdt gdt
lidt idt
/* 刷新环境 */
ljmp $0x8,$new_env
new_env:
mov $0x10,%eax
mov %eax,%ds
mov %eax,%es
mov %eax,%ss
mov %eax,%fs
mov %eax,%gs
mov $_STACK,%esp
call main
0:
hlt
jmp 0b

.data
envp:
.long 0x0
gdt:
.word 0xFFFF
.long GDT_TABLE
idt:
.word 256*8-1
.long IDT_TABLE
gdt_start:
CreateSection(0xAA,0,0XBB);
CreateSection(0x0,0xFFFFF,CODE_READ|CODE_D|CODE_G)
CreateSection(0x0,0xFFFFF,DATA_WRITE|DATA_G|R0|DATA_B);
CreateSection(0x0,0xFFFFF,CODE_READ|CODE_D|CODE_G|R3);
CreateSection(0x0,0xFFFFF,DATA_WRITE|DATA_G|R3|DATA_B);
CreateSection(TSS_TABLE,0x100,TSS|R3);
gdt_end:
BIN +1 KB kernel/setup.o
Binary file not shown.
@@ -0,0 +1,255 @@
#include "kernel.h"
#include <sys/sys.h>

#define INT_GATE 0x8e00
#define TRA_GATE 0x8f00
#define TR_GATE 0x8500
#define IDT_R0 0x0000
#define IDT_R1 0x2000
#define IDT_R2 0x4000
#define IDT_R3 0x6000


extern void divide_error(long,long *);
extern void single_step_exception(long,long *);
extern void nmi(long,long *);
extern void breakpoint_exception(long,long *);
extern void overflow(long,long *);
extern void bounds_check(long,long *);
extern void inval_opcode(long,long *);
extern void copr_not_available(long,long *);
extern void double_fault(long,long *);
extern void copr_seg_overrun(long,long *);
extern void inval_tss(long,long *);
extern void segment_not_present(long,long *);
extern void stack_exception(long,long *);
extern void general_protection(long,long *);
extern void page_fault(long,long *);
extern void copr_error(long,long *);
extern void none(long,long *);

extern void hwint00(void);
extern void hwint01(void);
extern void hwint02(void);
extern void hwint03(void);
extern void hwint04(void);
extern void hwint05(void);
extern void hwint06(void);
extern void hwint07(void);
extern void hwint08(void);
extern void hwint09(void);
extern void hwint10(void);
extern void hwint11(void);
extern void hwint12(void);
extern void hwint13(void);
extern void hwint14(void);
extern void hwint15(void);
extern int sys_call(int EAX,int EBX,int ECX,int EDX);


static unsigned long (* const idt)[2] = (unsigned long (*const)[2])(IDT_TABLE);

IrqHandler irq_table[NR_IRQ_VECTORS];

#define set_int(nr,func,section,attr) {\
idt[nr][0] = ((((unsigned int)func)&0xffff)|((unsigned short )(section)<<16));\
idt[nr][1] = ((((unsigned int)func)&0xffff0000)|(unsigned short)(attr));\
}


#define exit(n) panic("oop:-_-|\n");
static inline void die(char *str,long *reg,long nr){
printk("TRAP: %s %d.\nPROC:%d,%s\n",str,nr,act_proc->pid,act_proc->pname);
panic("^-^");
}

extern void do_divide_error(long code,long *reg){
die("divede error",reg,code);
}

extern void do_debug(long code,long *reg){
die("debug traps",reg,code);
printk("This debug!,But the code no ready![TRAP]\n");
}

extern void do_nmi(long code,long *reg){
die("nmi error!",reg,code);
}

extern void do_breakpoint(long code,long *reg){
die("breakpoint traps.",reg,code);
printk("code no ready![TRAP]\n");
}
extern void do_overflow(long code,long *reg){
die("overflow",reg,code);
}

extern void do_bounds_check(long code,long *reg){
die("bounds",reg,code);
}

extern void do_inval_opcode(long code,long *reg){
die("invalid operand",reg,code);
}

extern void do_copr_not_available(long code,long *reg){
die("copr not available.",reg,code);
}

extern void do_double_fault(long code,long *reg){
die("double fault",reg,code);
}

extern void do_copr_seg_overrun(long code,long *reg){
die("copr segment overrun",reg,code);
}

extern void do_inval_tss(long code,long *reg){
die("inval tss",reg,code);
}

extern void do_segment_not_present(long code,long *reg){
die("segment not present",reg,code);
}

extern void do_stack_exception(long code,long *reg){
die("stack segment",reg,code);
}

extern void do_general_protection(long code,long *reg){
die("general protection",reg,code);
}

extern void do_page_fault(long code,long *reg){
Message m = {};

__asm__("movl %%cr2,%0":"=r"(m.cr2));

}

extern void do_copr_error(long code,long *reg){
die("copr error",reg,code);
}

extern void do_none(long code,long *reg){
die("what the fuck!",reg,code);
}

extern void _null(void){
// die("-_-!",1);
;
}

extern void do_keyboard(void){
int _ch;
const char key[]=" `1234567890-=\15\tqwertyuiop[] asdfghjkl;' \r zxcvbnm,./ ";
_ch = inb(0x60);
if(_ch<sizeof(key));
//printk("%c",key[_ch]);
}

extern void disable_irq(int irq){
unsigned char mask;
unsigned char ctl;
if(NR_IRQ_VECTORS < irq || 0 > irq)
panic("invalid irq disable_irq");

if(irq > 7){
mask = 1 << (irq - 7);
ctl = INT2_CTLMASK;
}else{
mask = 1 << irq;
ctl = INT_CTLMASK;
}
cli();
mask |= inb(ctl);
outb(ctl,mask);
sti();
}

extern void enable_irq(int irq){
unsigned char mask;
unsigned char ctl;
if(NR_IRQ_VECTORS < irq || 0 > irq)
panic("invalid irq disable_irq");

if(irq > 7){
mask = ~(1 << (irq - 7));
ctl = INT2_CTLMASK;
}else{
mask = ~(1 << irq);
ctl = INT_CTLMASK;
}
cli();
mask &= inb(ctl);
outb(ctl,mask);
sti();
}

static int spurious_irq(int irq){
if(irq < 0 || irq >= NR_IRQ_VECTORS)
panic("invalid call to spurious_irq");
printk("spurious irq %d \n",irq);
return 1;
}

extern void put_irq_handler(int irq,IrqHandler handler){
if(irq < 0 || irq >= NR_IRQ_VECTORS)
panic("invalid call to put_irq_handler");
if(irq_table[irq] == handler)
return;
if(irq_table[irq] != spurious_irq)
panic("attempt to register second irq handler for irq");
disable_irq(irq);
irq_table[irq] = handler;
enable_irq(irq);
}

extern void trap_init(void){

/* install defualt int */
for(int i = 0;i<256;i++) set_int(i,none,KERNEL_CODE,(INT_GATE|IDT_R0));
set_int(0,divide_error,KERNEL_CODE,((TRA_GATE|IDT_R0)));
set_int(1,single_step_exception,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(2,nmi,KERNEL_CODE,(INT_GATE|IDT_R0));
set_int(3,breakpoint_exception,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(4,overflow,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(5,bounds_check,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(6,inval_opcode,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(7,copr_not_available,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(8,double_fault,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(9,copr_seg_overrun,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(10,inval_tss,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(11,segment_not_present,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(12,stack_exception,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(13,general_protection,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(14,page_fault,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(16,copr_error,KERNEL_CODE,(TRA_GATE|IDT_R0));


set_int(0x20,hwint00,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x21,hwint01,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x22,hwint02,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x23,hwint03,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x24,hwint04,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x25,hwint05,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x26,hwint06,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x27,hwint07,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x28,hwint08,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x29,hwint09,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x2a,hwint10,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x2b,hwint11,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x2c,hwint12,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x2d,hwint13,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x2e,hwint14,KERNEL_CODE,(TRA_GATE|IDT_R0));
set_int(0x2f,hwint15,KERNEL_CODE,(TRA_GATE|IDT_R0));

set_int(0x80,sys_call,KERNEL_CODE,(TRA_GATE|IDT_R3));

for(int i = 0;i < NR_IRQ_VECTORS;i++) irq_table[i] = spurious_irq;
Registers *clock_handler(Registers *);
irq_table[0] = (IrqHandler)clock_handler;

outb_p(~(0x1),INT_CTLMASK);
//outb_p(0x0,INT2_CTLMASK);
}
BIN +8.78 KB kernel/trap.o
Binary file not shown.
@@ -0,0 +1,40 @@
#ifndef __VGA_H__
#define __VGA_H__
#include <x86/io.h>

/* VGA register port */

#define VGA_ADDR 0x03d4 /* vga address port */
#define VGA_DATA 0x03d5 /* vga data port */
#define VGA_MODE 0x03d8 /* select vga model */
#define VGA_PALLET 0x03d9 /* vga pallet */
#define VGA_STATE 0x03da /* vga display state register */
#define VGA_RESET_LP 0x03db /* reset light pen */
#define VGA_SET_LP 0x03dc /* */

#define START_ADDR_H 0x0c /* reg index of video memory start addr High*/
#define START_ADDR_L 0x0d /* reg index of video memory start addr Low */
#define CURSOR_H 0x0e /* reg index of cursor position Hight */
#define CURSOR_L 0x0f /* reg index of cursor position Low */

/* CGA model console register*/


/* mc6845 data register */

/* write\read mc6845 register */

#define mc6845_read(port) ({\
unsigned char _d = 0; \
outb_p((port),VGA_ADDR); \
_d = inb_p(VGA_DATA); \
_d; \
})

#define mc6845_write(data,port) ({\
outb_p((port),VGA_ADDR); \
outb_p((data),VGA_DATA); \
})


#endif
@@ -0,0 +1,325 @@


#
#
# X86硬件相关处理包括x86中断,时钟中断,硬件中断等入口,系统调用入口也在该文件处理
#
#
#include <const.h>

.globl divide_error # 除法出错
.globl single_step_exception # 单步异常
.globl nmi # nmi
.globl breakpoint_exception # 断点
.globl overflow # 溢出
.globl bounds_check # 边界检测
.globl inval_opcode # 无效操作码
.globl copr_not_available # 协处理器无效
.globl double_fault # 双重错误
.globl copr_seg_overrun # 协处理器段越界
.globl inval_tss # 无效的任务段
.globl segment_not_present # 段不存在
.globl stack_exception # 栈异常
.globl general_protection # 常规错误
.globl page_fault # 页异常
.globl copr_error # 协处理器错误
.globl none
.globl sys_call
.globl switch_proc

.globl _null
.globl do_keybord
.globl do_call

.globl hwint00
.globl hwint01
.globl hwint02
.globl hwint03
.globl hwint04
.globl hwint05
.globl hwint06
.globl hwint07
.globl hwint08
.globl hwint09
.globl hwint10
.globl hwint11
.globl hwint12
.globl hwint13
.globl hwint14
.globl hwint15

.globl jiffies

.globl NR_syscalls,sys_call_table
.globl irq_table,act_registers,act_core



.macro save

pushal
pushl %es
pushl %ds
pushl %fs
pushl %gs
movl $0x10,%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
movl %eax,%gs
.endm

.macro recov
popl %gs
popl %fs
popl %ds
popl %es
popal
.endm

.text
# 除法出错处理
divide_error:
push $0 #人工设置错误号
pushl $do_divide_error
error_code:
xchgl %eax,4(%esp) #保存%eax,并将错误号放入%eax
pushl %ecx
pushl %edx
xchgl %ebx,8(%esp) #保存%ebx,并将处理函数指针放入%ebx
pushl %ebp
pushl %esi
pushl %edi
pushl %es
pushl %ds
pushl %fs
pushl %gs
pushl %esp
pushl %eax
movl $0x10,%eax
movw %ax,%ds
movw %ax,%es
movw %ax,%fs
call *%ebx
addl $8,%esp
popl %gs
popl %fs
popl %ds
popl %es
popl %edi
popl %esi
popl %ebp
popl %ebx
popl %edx
popl %ecx
popl %eax
iret

# 调试中断
single_step_exception:
pushl $0
pushl $do_debug
jmp error_code

#_nmi
nmi:
pushl $0
pushl $do_nmi
jmp error_code

breakpoint_exception:
pushl $0
pushl $do_breakpoint
jmp error_code

overflow:
pushl $0
pushl $do_overflow
jmp error_code

bounds_check:
pushl $0
push $do_bounds_check
jmp error_code

inval_opcode:
pushl $0
pushl $do_inval_opcode
jmp error_code

copr_not_available:
pushl $0
pushl $do_copr_not_available
jmp error_code

double_fault:
pushl $do_double_fault
jmp error_code

copr_seg_overrun:
pushl $0
pushl $do_copr_seg_overrun
jmp error_code

inval_tss:
pushl $do_inval_tss
jmp error_code

segment_not_present:
pushl $do_segment_not_present
jmp error_code

stack_exception:
pushl $do_stack_exception
jmp error_code

general_protection:
pushl $do_general_protection
jmp error_code

page_fault:
pushl $do_page_fault
jmp error_code

copr_error:
pushl $0
pushl $do_copr_error
jmp error_code

none:
pushl $0
pushl $do_none
jmp error_code

# hwint01-07
#
#define hwint_master(irq) \
save; \
inb $INT2_CTLMASK,%al; \
orb $(1<<(irq)),%al; \
outb %al,$INT_CTLMASK; \
movb $0x20,%al; \
outb %al,$INT_CTL; \
movl $irq,%eax;\
sti; \
push $irq; \
call *irq_table(,%eax,4); \
addl $4,%esp; \
cli; \
inb $INT_CTLMASK,%al; \
andb $(~(1<<(irq))),%al; \
outb %al,$INT_CTLMASK; \
recov; \
iret;

hwint00:
save;
inb $INT2_CTLMASK,%al;
orb 1,%al;
outb %al,$INT_CTLMASK;
movb $0x20,%al;
outb %al,$INT_CTL;

incl jiffies

#sti;
pushl %esp
movl $0,%eax
call *irq_table(,%eax,4) //不用恢复ESP
movl %eax,%esp
0:
inb $INT_CTLMASK,%al;
andb $(~1),%al;
outb %al,$INT_CTLMASK;
recov;
iret;

hwint01:
hwint_master(1);
hwint02:
hwint_master(2);
hwint03:
hwint_master(3);
hwint04:
hwint_master(4);
hwint05:
hwint_master(5);
hwint06:
hwint_master(6);
hwint07:
hwint_master(7);
# hwinnt09-15
#define hwint_slave( irq) \
save; \
inb $INT2_CTLMASK,%al; \
orb $(1<<(irq-8)),%al; \
outb %al,$INT2_CTLMASK; \
movb $0x20,%al; \
outb %al,$INT_CTL; \
jmp .+2; \
outb %al,$INT2_CTL; \
movl $irq,%eax;\
sti; \
pushl $irq; \
call *irq_table(,%eax,4); \
addl $4,%esp;\
cli; \
inb $INT2_CTLMASK,%al; \
andb $(~(1<<(irq-8))),%al; \
outb %al,$INT2_CTLMASK; \
recov; \
iret;
hwint08:
hwint_slave(8);
hwint09:
hwint_slave(9);
hwint10:
hwint_slave(10);
hwint11:
hwint_slave(11);
hwint12:
hwint_slave(12);
hwint13:
hwint_slave(13);
hwint14:
hwint_slave(14);
hwint15:
hwint_slave(15);

bad_sys_call:
movl $-1,%eax
jmp ret_from_sys_call
# eax = function args = {ebx ,ecx,edx}
sys_call:
cli
pushl %ds
pushl %es
pushl %fs
pushl %esi
pushl %edi
pushl %edx
pushl %ecx
pushl %ebx

cmpl NR_syscalls,%eax
jae bad_sys_call

movl $KERNEL_DATA,%edx
movl %edx,%ds
movl %edx,%es
movl %edx,%fs

sti
call *sys_call_table(,%eax,4)

ret_from_sys_call:
popl %ebx
popl %ecx
popl %edx
popl %edi
popl %esi
popl %fs
popl %es
popl %ds
sti
iret
BIN +3.8 KB kernel/x86.o
Binary file not shown.
@@ -0,0 +1,37 @@
# Makefile for all
#
.PHONY:clear install make

# Directories
i = $r/include
l = libc.a
vpath %.h $r/include/

# Programs, flags, etc.
AS = as
CC = gcc
LD = ld

ASFLAGS = --32
CFLAGS = -I $i -m32 -c -std=gnu99 -fno-stack-protector -Wall -nostdinc
LDFLAGS = -m elf_i386 -Ttext 0x300000

OBJS = vsprintf.o string.o malloc.o
# What to make.
#

$l:$(OBJS)
$(AR) -r $@ $^

%.o:%.S
$(CC) $< -o $@ $(CFLAGS)

%.o:%.c
$(CC) $< -o $@ $(CFLAGS)

%.o:%.s
$(AS) $< -o $@ $(ASFLAGS)


clear:
-rm *.o -rf
BIN +7.5 KB lib/libc.a
Binary file not shown.
@@ -0,0 +1,129 @@
/*
* Copy form linux 0.12 .
*
*/
#include <const.h>
#include <stdio.h>
#include <types.h>
#include <sys/inter.h>

#define isnull(p) (!(p))
/* get page pointer */
#define get_pointer(p) ((p) & 0xfffff000)

typedef struct _bucket{
void *page;
struct _bucket *next;
void *freeptr;
unsigned short refcnt;
unsigned short bucket_size;
}Bucket;

struct _bucket_dir{
int size;
Bucket *bucket;
};

struct _bucket_dir bucket_dir[] = {
{16,NULL},
{32,NULL},
{64,NULL},
{128,NULL},
{256,NULL},
{512,NULL},
{1024,NULL},
{2048,NULL},
{4096,NULL},
{0,NULL},
};

Bucket *free_bucket = NULL;

static inline void bucket_init(void){
Bucket *first,*bdesc;

first = bdesc = (Bucket *)(get_free_page());
if(isnull(bdesc)) panic("Out of memory in init bucket_init!\n");
for(int i = PAGE_SIZE / sizeof(Bucket);i > 1;i--){
bdesc->next = bdesc + 1;
bdesc++;
}
bdesc->next = free_bucket;
free_bucket = first;
}

void *malloc(unsigned int len){
Bucket *bdesc;
struct _bucket_dir *bdir;
void *retval = NULL;
for(bdir = bucket_dir;bdir->size;bdir++)
if(bdir->size > len)
break;
if(!bdir->size) panic("Don't alloc the memory!\n");
lock();
for(bdesc = bdir->bucket;bdesc;bdesc = bdesc->next)
if(bdesc->freeptr)
break;
if(isnull(bdesc)){
char *cp = NULL;
if(isnull(free_bucket)) bucket_init();
bdesc = free_bucket;
free_bucket = free_bucket->next;
bdesc->refcnt = 0;
bdesc->bucket_size = bdir->size;
bdesc->page = bdesc->freeptr = cp = (void *)(get_free_page());
if(isnull(cp)) panic("Out of memory in kernel malloc()\n");
for(int i = PAGE_SIZE / bdir->size;i > 1;i--){
*((char **)cp) = cp + bdir->size;
cp += bdir->size;
}
*((char **)cp) = NULL;
bdesc->next = bdir->bucket;
bdir->bucket = bdesc;
}
retval = bdesc->freeptr;
bdesc->freeptr = *((void **) retval);
bdesc->refcnt++;
unlock();
return retval;
}

void free_s(void *obj,int size){
void *page;
struct _bucket_dir *bdir;
Bucket *bdesc,*prev;

page = (void *)(get_pointer((Pointer)obj));

for(bdir = bucket_dir;bdir->size;bdir++){
prev = NULL;
if(bdir->size < size) continue;
for(bdesc = bdir->bucket;bdesc;bdesc = bdesc->next){
if(bdesc->page == page)
goto found;
prev = bdesc;
}
}
panic("Bad address passed to kernel free_s()");
found:
lock();
*((void **)obj) = bdesc->freeptr;
bdesc->refcnt--;
if(bdesc->refcnt == 0){
if((prev && (prev->next != bdesc)) || (!prev && (bdir->bucket != bdesc)))
for(prev = bdir->bucket;prev;prev = prev->next)
if(prev->next == bdesc)
break;
if(prev)
prev->next = bdesc->next;
else{
if(bdir->bucket != bdesc)
panic("malloc bucket corrupted\n");
bdir->bucket = bdesc->next;
}
free_page((Pointer)bdesc->page);
bdesc->next = free_bucket;
free_bucket = bdesc;
}
unlock();
}
BIN +2.42 KB lib/malloc.o
Binary file not shown.
@@ -0,0 +1,32 @@
#include <string.h>
#include <stddef.h>
void *memcpy(void *dest,const void *src,int n){
asm("cld\n\t"
"rep\n\t"
"movsb\n\t"
:
:"c"(n),"S"(src),"D"(dest)
:
);
return dest;
}
void *memset(void *dest,int ch,int n){
asm("0:movb %%al,(%1)\n\t"
"inc %1\n\t"
"loop 0b\n\t"
:
:"a"(ch),"D"(dest),"c"(n)
:);
return dest;
}

char *strcpy(char *dest,const char *src){
asm("0:lodsb\n\t\t"
"stosb\n\t\t"
"test %%al,%%al\n\t\t"
"jne 0b\n\t\t"
:
:"D"(dest),"S"(src)
:);
return dest;
}
BIN +1.06 KB lib/string.o
Binary file not shown.
@@ -0,0 +1,211 @@
/*
*/
#include <stdarg.h>
/* 数值转换成以base为基数的字符串,保存在str中 */
typedef enum _HexBase{
OCTAL = 8,
DECIMAL = 10,
HEX = 16
}HexBase;

typedef enum{
_false = 0,
_true = 1,
}_bool;
//输出样式
// <space>|<sign>|<special>|<zero>|num|<space>
#define STYLE_LEFT 1 //左对齐
#define STYLE_SIGN ((STYLE_LEFT)<<1) //负数时显示'-'号,正数时显示'+'
#define STYLE_SPECIAL ((STYLE_LEFT)<<2) //显示进制前缀
#define STYLE_ZEROPAD ((STYLE_LEFT)<<3) //用零填充不足的位宽
#define STYLE_LARGE ((STYLE_LEFT)<<4) //使用大写字母

//数字字符表
static const char * const _lowerDigits = "0123456789abcdefx";
static const char * const _upperDigits = "0123456789ABCDEFX";

#define isDigit(c) ((c) >= '0' && (c) <= '9')
//
static inline int _atoi(const char **s){
int i = 0;
while(isDigit(**s)) i = i * 10 + *((*s)++) - '0';
return i;
}
//进制转换
static inline int _octal(int *str,unsigned long value){
int i = 0;
do{
*str++ = value & 7;
value >>= 3;
i++;
}while(value);
return i;
}
static inline int _decimal(int *str,unsigned long value){
int i = 0;
do{
*str ++ = value % 10;
value /= 10;
i++;
}while(value);
return i;
}
static inline int _hex(int *str,unsigned long value){
int i = 0;
do{
*str++ = value & 0xf;
value >>= 4;
i++;
}while(value);
return i;
}

static inline char *_toNumber(char *str,long value,_bool sign,
HexBase base,int size,int style){
char signString = '+';
const char *dig = _lowerDigits;
int tmp[64]; //缓存转换后的值.还不是ASCII
int length = 0;

if(style & STYLE_LARGE) dig = _upperDigits;
if(style & STYLE_LEFT) style &= (~STYLE_ZEROPAD); //左对齐就不能使用0填充
//如果不是10进制,则都按无符号处理 ,并且无正负符号显示
//如果是10进制,则去除前缀属性
if(DECIMAL != base){
sign = _false;
style &= ~STYLE_SIGN;
} else style &= ~STYLE_SPECIAL;

if(style & STYLE_SPECIAL){
if(HEX == base) size -= 2;
else if(OCTAL == base) size -= 1;
}

//如果是有符号数,却小于0,则取其补码,并设置符号标志,非16进制在前面已经去除
//符号,所以不会受影响
if((_true == sign) && (value < 0)){
style |= STYLE_SIGN;
value = ~value + 1;
signString = '-';
}

if(style & STYLE_SIGN) size --;

switch(base){
case OCTAL:length = _octal(tmp,(unsigned long)value);break;
case DECIMAL:length = _decimal(tmp,(unsigned long)value);break;
case HEX:length = _hex(tmp,(unsigned long)value);break;
}
size -= length;

if(!(style & (STYLE_ZEROPAD|STYLE_LEFT))) while(size-- > 0) *str++ = ' ';
if(style & STYLE_SIGN) *str++ = signString;
if(style & STYLE_SPECIAL){
*str++ = '0';
if(HEX == base) *str++ = dig[0x10];
}
if(style & STYLE_ZEROPAD) while(size-- > 0) *str++ = '0';
while(length-- > 0) *str++ = dig[tmp[length]];
if(style & STYLE_LEFT) while(size-- > 0) *str++ = ' ';

return str;
}

extern int vsprintf(char *buf,const char *fmt,va_list args){
int style = 0;
int width = 0;
unsigned long num = 0;
_bool sign = _true;
HexBase base = DECIMAL;
char *str,*s;

enum type{ _long = 'L', _int = 'l' , _short = 'h' }_type = _int; //数据类型,long,int,short

for( str = buf; *fmt; fmt++){
if(*fmt == '%'){
style = 0;
repeat:
fmt++;
switch(* fmt){
case '-': style |= STYLE_LEFT;goto repeat;
case '+': style |= STYLE_SIGN;goto repeat;
case ' ': style |= STYLE_SIGN;goto repeat;
case '0': style |= STYLE_ZEROPAD;goto repeat;
case '#': style |= STYLE_SPECIAL;goto repeat;
}
width = 0;
if(isDigit(*fmt))
width = _atoi(&fmt);
else if(* fmt == '*'){
fmt++;
width = va_arg(args,int);
}
_type = _int;
if(*fmt == 'h' || *fmt == 'l' || *fmt == 'L'){
_type = (enum type)(*fmt);
fmt++;
}
base = DECIMAL;
sign = _false;

switch(*fmt){
case 'c':*str++ = (unsigned char)va_arg(args,int);continue;
case 's':
s = va_arg(args,char *);
if(!s) s = "<NULL>";
while(*s) *str++ = *s++;
continue;
case 'p':
style |= STYLE_SPECIAL;
str = _toNumber(str,(unsigned long)va_arg(args,void *),
_false,HEX,width,style);
continue;
case 'o':base = OCTAL;break;
case 'X':style |= STYLE_LARGE;
case 'x':base = HEX;style |= STYLE_SPECIAL;break;
case 'd':
case 'i': sign = _true;
case 'u': break;
default: if(*fmt) *str++ = *fmt; continue;
}
if ( _long == _type )
num = va_arg( args, unsigned long );
else if ( _short == _type ){
if ( _true == sign )
num = va_arg( args, int );
else
num = va_arg( args, unsigned int );
}
else if ( _true == sign )
num = va_arg( args, int );
else
num = va_arg( args, unsigned int );

str = _toNumber(str,num,
_false,base,width,style);
}
else
*str++ = *fmt;
}
*str = 0;

return (buf - str);
}

extern int sprintf(char *buf,const char * fmt,...){
va_list args;
int n;
va_start(args,fmt);
n = vsprintf(buf,fmt,args);
va_end(args);
return n;
}
/*
int main(void){
#include <string.h>
char buf[1200]={0};
sprintf(buf,"|Hello %c %-d %u %#08x %#o %s\n",'a',30,40,0xaa,010,"ni hao!");
#include <stdio.h>
puts(buf);
}
*/
BIN +3.66 KB lib/vsprintf.o
Binary file not shown.
163 setup.S
@@ -0,0 +1,163 @@
/*
* (C) 2011-10
* Email:LuoZhongYao@gmail.com
* 每天都对自己说:"Good luck!"
* 该程序负责初始化内核工作环境,是内核执行的第一个程序.
* 初始化内容包括,重新安排GDT(由multiboot规范知道,现在已经有一个GDT了),并且
* 对8259进行初始化,本质上来说,该程序只是原gmL的setup去除进入保护模式和添加
* multiboot支持而已.
* 使用multiboot的好处是可以使用现存的文件系统,而不用去研究它,可以被其
* 引导器引导.内核大小没有限制.反正很多啦,所以我个人建议,有写内核的同学,必
* 要参考multiboot,并遵守它.
*/
/* 汇编代码 */
#define ASM
/* multiboot规范头文件,该文件直接拷贝于grub_0.98/docs/multiboot.h */
#include <multiboot.h>

#define CreateSection(base,limit,attr) \
.short limit&0xffff;\
.short base&0xffff; \
.byte (base>>16)&0xff;\
.short (attr)|((limit>>8)&0x0f00);\
.byte (base>>24)&0xff;\
//代码段相关属性宏定义
#define CODE_READ 0x009a //代码段可读
#define CODE_C 0x009c //一致代码段
#define CODE_G 0x8098 //使用4GB的界限
#define CODE_D 0x4098 //默认使用32位地址
//数据段属性
#define DATA_WRITE 0x0092 //数据段可写
#define DATA_E 0x0094 //向下扩展
#define DATA_G 0x8090 //使用32界限
#define DATA_B 0x4090 //堆栈段使用ESP等32位指针,向下扩展,指明栈上限4GB
//TSS描述符
#define TSS_G 0x8089 //TSS使用4GB界限,通常这个是用不到的
#define TSS 0x0089 //说明这是一个TSS段
//权限
#define R0 0x0000 //ring 0
#define R1 0x0020 //
#define R2 0x0040 //
#define R3 0x0060 //ring 3

GDT_LEN = gdt_end-gdt_start
/*
#define io_delay \
jmp .+2 \
jmp .+2
*/
/* IO延时宏 */
.macro io_delay
jmp .+2
jmp .+2
.endm
.text
.globl _start,envp,main
_start:
jmp start
/* multiboot 要求4字节对齐 */
.align 4
multiboot_header:
/* multiboot header magic 详情请查阅multiboot */
.long MULTIBOOT_HEADER_MAGIC
/* multiboot header flags multiboot为你做什么服务,色情服务不在这个范围内*/
/* 同时也告诉了multiboot你是什么款式的人,oh,程序 */
.long MULTIBOOT_HEADER_FLAGS
/* multiboot header checksum ,详情请看multiboot */
/* 我猜测引导器就是靠checksum和magic来识别multiboot header的. */
.long -(MULTIBOOT_HEADER_MAGIC+MULTIBOOT_HEADER_FLAGS)
/* 如果不是ELF文件格式,下面的信息就是必须的,这个__ELF__不知道是在哪里定义的 */
/* 不过我的二进制,就算下面这些提供了,grub还是不鸟我,所以我也不鸟二进制 */
#ifndef __ELF__
/* multiboot header addr,hi哥们,你在哪? */
.long multiboot_header
/* Load addr .text在OSimage中的偏移 */
.long _start
/* Load end addr 引导到OSimage中那个位置,如果为零,引导整个OS Image */
.long _edata
/* bss段的结束地址.Boot loader将其清零,并且保证不被覆盖 */
.long _end
/* Boot loader 引导完后将跳转到这里执行 */
.long _start
#endif
start:
cli
/*
mov $0x3FFFF0,%esp
push %ebx
*/
/* 保存由Boot loader提供的信息地址 */
mov %ebx,envp
/* 8259,写过很多次了,懒得在写,不懂的可以google,或者Email我 */
/* 唯一说一点的就是外部中断0x20~0x30 */
mov $0x11,%al
out %al,$0x20
io_delay
out %al,$0xa0
io_delay

mov $0x20,%al
out %al,$0x21
io_delay
mov $0x28,%al
out %al,$0xa1
io_delay

mov $0x04,%al
out %al,$0x21
io_delay
mov $0x2,%al
out %al,$0xa1
io_delay

mov $0x1,%al
out %al,$0x21
io_delay
out %al,$0xa1
io_delay

/* 屏蔽外部中断 */
mov $0xFF,%al
out %al,$0x21
io_delay
out %al,$0xa1
io_delay
/* 重新设置GDT,GDT被放置到0x101000处 */
mov $GDT_TABLE,%edi
mov $gdt_start,%esi
mov $GDT_LEN,%ecx
shr $2,%ecx
cld
rep movsl
lgdt gdt
lidt idt
/* 刷新环境 */
ljmp $KERNEL_CODE,$new_env
new_env:
mov $KERNEL_DATA,%eax
mov %eax,%ds
mov %eax,%es
mov %eax,%ss
mov %eax,%fs
mov %eax,%gs
mov $DIE_STACK,%esp
call main
jmp .

.data
envp:
.long 0x0
gdt:
.word 0xFFFF
.long GDT_TABLE
idt:
.word 256*8-1
.long IDT_TABLE
gdt_start:
CreateSection(0xAA,0,0XBB);
CreateSection(0x0,0xFFFFF,CODE_READ|CODE_D|CODE_G)
CreateSection(0x0,0xFFFFF,DATA_WRITE|DATA_G|R0|DATA_B);
CreateSection(0x0,0xFFFFF,CODE_READ|CODE_D|CODE_G|R3);
CreateSection(0x0,0xFFFFF,DATA_WRITE|DATA_G|R3|DATA_B);
CreateSection(TSS_TABLE,0x100,TSS|R3);
gdt_end: