⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 一个类linux的dos下开发的操作系统.
💻 C
字号:
/*****************************************************************************
MAIN KERNEL

EXPORTS:
extern task_t _tasks[];
extern volatile task_t *_curr_task;

void kprintf(const char *fmt, ...);
void wake_up(wait_queue_t *queue);
int sleep_on(task_t *curr_task, wait_queue_t *queue, unsigned *timeout);
task_t *fault(volatile regs_t regs);
int main(void);
*****************************************************************************/
#include <_printf.h> /* do_printf() */
#include <string.h> /* memcmp() */
#include <_sys.h> /* SYS_... */
#include <krnl.h> /* MAX_VC, TS_..., task_t, read_le32() */
#include <x86.h> /* outportb() */

/* IMPORTS
from STARTUP.ASM */
//unsigned long get_page_dir(void);
void halt(void);

extern unsigned long _conv_mem_size, _ext_mem_size;
extern unsigned long _kvirt_to_phys, _init_ramdisk_adr;

/* from DEBUG.C */
void dump_regs(regs_t *regs);

/* from PAGING.C */
int page_fault(task_t *curr_task, unsigned long err_code);
int init_paging(void);

/* from LOADER.C */
int run(task_t *task, unsigned char *image);

/* from VIDEO.C */
extern console_t _vc[];
extern unsigned short _num_vc;
extern volatile console_t *_curr_vc;

void blink(void);
void putch(console_t *con, unsigned char c);
void init_console(void);

/* from SYSCALLS.C */
void sys_exit(task_t *curr_task, int exit_code);
bool syscall(task_t *curr_task, volatile regs_t *regs);

/* from KBD.C */
void kbd_irq(void);
void init_kbd(void);

/* from kernel linker script file */
extern unsigned char code[], d_code[], data[], d_data[], bss[], end[];

task_t _tasks[MAX_TASK];
volatile task_t *_curr_task; /* used by asm task-switch code */
/*****************************************************************************
*****************************************************************************/
static int kprintf_help(char c, void **ptr)
{
	putch(_curr_vc, c);
	return 0;
}
/*****************************************************************************
*****************************************************************************/
void kprintf(const char *fmt, ...)
{
	va_list args;

	va_start(args, fmt);
	(void)do_printf(fmt, args, kprintf_help, NULL);
	va_end(args);
}
/*****************************************************************************
*****************************************************************************/
static void panic(const char *fmt, ...)
{
	va_list args;

	disable();
	va_start(args, fmt);
	(void)do_printf(fmt, args, kprintf_help, NULL);
	halt();
}
/*****************************************************************************
*****************************************************************************/
DISCARDABLE_CODE(static int init_tasks(unsigned char *image))
{
	unsigned char *rdsk_dir, *exec_file;
	unsigned short num_objs, t, o;
	task_t *task;

/* make sure it's a valid initial RAM disk */
	if(memcmp(image, "RDSK", 4))
	{
		kprintf("init_tasks: did not find RDSK signature\n");
		return -1;
	}
/* the number of objects in the image is right after the signature */
	num_objs = read_le32(image + 4);
	t = 1;
	for(o = 1; o < num_objs; o++)
	{
/* don't run more tasks than we have virtual consoles */
		if(t >= _num_vc)
			break;
		kprintf("obj %02u -> task %02u,  ", o, t);
/* point to the 24-byte directory entry in the image for this task */
		rdsk_dir = image + 8 + 24 * o;
/* get offset of object from directory of image; point to executable file */
		exec_file = read_le32(rdsk_dir + 0) + image;
/* try loading as DJGPP COFF */
		task = _tasks + t;
		if(run(task, exec_file) != 0)
			continue;
/* set other task stuff */
		task->status = TS_RUNNABLE;
		task->vc = _vc + t;
		t++;
	}
	kprintf("\n");
/* return nonzero if no tasks were loaded */
	return (t == 1) ? -1 : 0;
}
/*****************************************************************************
*****************************************************************************/
void wake_up(wait_queue_t *queue)
{
	task_t *task, *next;

/* make sure queue is not empty */
	task = queue->head;
	if(task == NULL)
		return;
/* mark head task in queue runnable */
	task->status = TS_RUNNABLE;
/* remove head task from queue */
	next = task->next;
	queue->head = next;
	if(next != NULL)
		next->prev = NULL;
	else
		queue->tail = NULL;
}
/*****************************************************************************
*****************************************************************************/
int sleep_on(task_t *curr_task, wait_queue_t *queue, unsigned *timeout)
{
	int ret_val = 0;
	task_t *prev;

/* mark task blocked */
	curr_task->status = TS_BLOCKED;
/* splice into wait queue at queue->tail */
	prev = queue->tail;
	queue->tail = curr_task;
	if(prev == NULL)
	{
		queue->head = curr_task;
		curr_task->prev = NULL;
	}
	else
	{
		curr_task->prev = prev;
		prev->next = curr_task;
	}
	curr_task->next = NULL;
/* set the timeout, if there is one */
	if(timeout != NULL)
		curr_task->timeout = *timeout;
	else
		curr_task->timeout = 0;
/* "fake" a timer interrupt. timer_irq() must detect this */
	__asm__ __volatile__("int $0x20");
/* now: why did we return? */
	if(timeout != NULL)
	{
		*timeout = curr_task->timeout;
/* there was a timeout, so timer_irq() awoke us. Return -1 */
		if(*timeout == 0)
			ret_val = -1;
	}
/* someone called wake_up(), making us TS_RUNNABLE again. Return 0 */
	return ret_val;
}
/*****************************************************************************
*****************************************************************************/
void schedule(void)
{
	static unsigned current;

	do
	{
		current++;
		if(current >= MAX_TASK)
			current = 0;
		_curr_task = _tasks + current;
	} while(_curr_task->status != TS_RUNNABLE);
}
/*****************************************************************************
xxx - calculation of timeouts is fubar
*****************************************************************************/
static void timer_irq(unsigned long eip)
{
	unsigned new_time;
//	unsigned char *instr;
	unsigned short i;

/* was it a real timer interrupt? */
//	if(inportb(0x20) & 0x01)

// xxx - this causes page fault in kernel mode
// (does it? check again)
//	instr = (unsigned char *)eip - 2;
//	if(*instr != 0xCD)
	{
/* decrement timeouts for tasks that have them */
		for(i = 0; i < MAX_TASK; i++)
		{
			new_time = _tasks[i].timeout;
			if(new_time == 0)
				continue;
/* number of microseconds per timer IRQ */
			new_time -= (1000000L / HZ);
			if(new_time > _tasks[i].timeout)
				new_time = 0;	/* underflow */
			_tasks[i].timeout = new_time;
/* timeout? wake up task */
			if(new_time == 0 && _tasks[i].status == TS_BLOCKED)
				_tasks[i].status = TS_RUNNABLE;
		}
//		outportb(0x20, 0x20); /* reset 8259 chip */
	}
outportb(0x20, 0x20);
/* run the scheduler, whether the interrupt was hardware (IRQ 0)
or software (INT 20h) */
	schedule();
}
/*****************************************************************************
*****************************************************************************/
task_t *fault(volatile regs_t regs)
{
	static const char *msg[] =
	{
		"divide error", "debug exception", "NMI", "INT3",
		"INTO", "BOUND exception", "invalid opcode", "no coprocessor",
		"double fault", "coprocessor segment overrun",
			"bad TSS", "segment not present",
		"stack fault", "GPF", "page fault", "??",
		"coprocessor error", "alignment check", "??", "??",
		"??", "??", "??", "??",
		"??", "??", "??", "??",
		"??", "??", "??", "??"
		"IRQ0", "IRQ1", "IRQ2", "IRQ3",
		"IRQ4", "IRQ5", "IRQ6", "IRQ7",
		"IRQ8", "IRQ9", "IRQ10", "IRQ11",
		"IRQ12", "IRQ13", "IRQ14", "IRQ15",
		"syscall"
	};
	task_t *ret_val;

/* return old value of _curr_task to asm code,
so it can determine if a task-switch occurred */
	ret_val = _curr_task;
	switch(regs.which_int)
	{
/* page fault */
		case 0x0E:
			if(page_fault(_curr_task, regs.err_code) != 0)
				goto ERR;
			break;
/* timer (IRQ 0) */
		case 0x20:
			blink();
			timer_irq(regs.eip);
			break;
/* keyboard (IRQ 1) */
		case 0x21:
			kbd_irq();
			outportb(0x20, 0x20);
			break;
/* int 30h (syscall) */
		case SYSCALL_INT:
			if(syscall(_curr_task, &regs))
				schedule();
			break;
/* anything else */
		default:
ERR:			kprintf("Exception #%u ", regs.which_int);
			if(regs.which_int <= sizeof(msg) / sizeof(char *))
				kprintf("(%s) ", msg[regs.which_int]);
/* oops, it happened in kernel mode */
			if((regs.cs & 3) == 0)
			{
				kprintf("in kernel mode.\n");
				dump_regs(&regs);
				panic("System halted\n");
			}
/* else user mode fault: kill the task */
			kprintf("in user mode; task %u killed\n",
				_curr_task - _tasks);
			sys_exit(_curr_task, -1);
			break;
	}
	return ret_val;
}
/*****************************************************************************
*****************************************************************************/
DISCARDABLE_CODE(static void init_8259s(void))
{
	outportb(0x20, 0x11); /* ICW1 */
	outportb(0xA0, 0x11);

	outportb(0x21, 0x20); /* ICW2: route IRQs 0...7 to INTs 20h...27h */
	outportb(0xA1, 0x28); /* ...IRQs 8...15 to INTs 28h...2Fh */

	outportb(0x21, 0x04); /* ICW3 */
	outportb(0xA1, 0x02);

	outportb(0x21, 0x01); /* ICW4 */
	outportb(0xA1, 0x01);
/* enable IRQ0 (timer) and IRQ1 (keyboard) */
	outportb(0x21, ~0x03);
	outportb(0xA1, ~0x00);
}
/*****************************************************************************
*****************************************************************************/
DISCARDABLE_CODE(static void init_8253(void))
{
/* I can remember the NTSC TV color burst frequency, but not the PC
peripheral clock. Fortunately, they are related: */
	static const unsigned short foo = (3579545L / 3) / HZ;

/* reprogram the 8253 timer chip to run at 'HZ', instead of 18 Hz */
	outportb(0x43, 0x36);	/* channel 0, LSB/MSB, mode 3, binary */
	outportb(0x40, foo & 0xFF);	/* LSB */
	outportb(0x40, foo >> 8);	/* MSB */
}
/*****************************************************************************
for MinGW32
*****************************************************************************/
#ifdef __WIN32__
int __main(void) { return 0; }
#endif
/*****************************************************************************
*****************************************************************************/
int main(void)
{
	unsigned keep, discard, temp;
//	unsigned long *cr3;

	init_console();
	kprintf("\x1B[31m""C""\x1B[32m""o""\x1B[33m""s""\x1B[34m""m"
		"\x1B[35m""o""\x1B[36m""s""\x1B[37m"" OS release 10 "
		"- Copyright (C) 2001 Chris Giese <geezer@execpc.com>\n");
	kprintf("%uK conventional memory, %uK extended memory. "
		"Virt-to-phys=0x%X,\n", _conv_mem_size >> 10,
		_ext_mem_size >> 10, _kvirt_to_phys);
	kprintf("kernel virtual address=0x%X, physical address=0x%X\n",
		code, code + _kvirt_to_phys);
	keep = (d_code - code) + (d_data - data) + (end - bss);
	discard = (data - d_code) + (bss - d_data) + 0;
	kprintf("Kernel memory:\tcode\tdata\tbss\tTOTAL\n"
		"\tTOTAL\t%u\t%u\t%u\t%u\n"
		"\tDISCARD\t%u\t%u\t%u\t%u\n"
		"\tKEEP\t%u\t%u\t%u\t%u\t(all values in bytes)\n",
		data - code,	bss - data,	end - data, keep + discard,
		data - d_code,	bss - d_data,	0,		discard,
		d_code - code,	d_data - data,	end - data,	keep);
	init_kbd();
kprintf("calling init_8259s\n");
	init_8259s();
kprintf("calling init_8253\n");
	init_8253();
kprintf("calling init_paging\n");
/* initialize the page tables for task #0 */
	temp = init_paging();
	if(temp != 0)
	{
		kprintf("init_paging returned %d\n", temp);
		halt();
	}
if(_init_ramdisk_adr == 0)
{kprintf("foo!"); halt(); }

/* init tasks */
_curr_task = _tasks + 0;
kprintf("calling init_tasks\n");
	temp = init_tasks((unsigned char *)_init_ramdisk_adr);
	if(temp != 0)
	{
		kprintf("sorry, did not find any tasks to run\n");
		halt();
	}
/* done with init, can now discard init-only code/data */
//	kprintf("Discarding %u bytes kernel memory...\n", discard);
//	cr3 = (unsigned long *)get_page_dir();
//	(void)unmap_mem(cr3, (unsigned long)d_code, data - d_code);
//	(void)unmap_mem(cr3, (unsigned long)d_data, bss - d_data);
/* xxx - do I need to do invalidate() ? */
	kprintf("press F1, F2, etc. to select virtual console\n");
/* enabling timer interrupt starts the scheduler */
	enable();
/* freeze */
	while(1)
		halt();
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -