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

📄 main.c

📁 一个操作系统,用C语言实现开发的,我在一个浙江大学的操作系统实验网站找到.大家学习以下
💻 C
字号:
// Loader for XSFS

asm(".code16");

#include <knldefs.h>
#include <knlinit.h>
#include <memory.h>
#include <string.h>
#include <xsfs.h>
#include <xsfstree.h>

#define EXT_INT13	0x8000

_u16 _bs_dx, _bs_ext;
_u32 _bs_base, _bs_part;
XSFSDESC _bs_xsfs;

// local data
static void* _buffer;
static char sz_err_disk[] = "Disk read error";

#ifdef __DEBUG__
void u32tohex(_u32 val, char *buf);
void dbg0(void);
_u8 WaitKey(void);
void ClearSrc(void);
#endif

void display(char *str)
{
	asm("display_next: \n"
		"lodsb; cmpb $0, %%al; jz display_end\n"
		"pushw %%si; movw $0x0007, %%bx; movb $0x0e, %%ah\n"
		"int $0x10; popw %%si; jmp display_next\n"
		"display_end:"::"S"(str));
}

static int read_sector(_u32 pos)
{
	int ret;
	if(_bs_ext&EXT_INT13)
	{
		char buf[16];
		asm("movb $0x10, 0(%%ebx); movb $0, 1(%%ebx); movw $1, 2(%%ebx)\n"
			"movw %%ax, 4(%%ebx); movw %%ds, %%ax; movw %%ax, 6(%%ebx)\n"
			"movl %%ecx, 8(%%ebx); movl $0, 12(%%ebx); movw %%bx, %%si\n"
			"movw $0x4200, %%ax; int $0x13; jb read_sector_err\n"
			"xorl %%eax, %%eax\n"
			"read_sector_err:":"=a"(ret):"a"(_buffer), "b"(buf), "c"(_bs_base+pos), "d"(_bs_dx));
	}
	return ret;
}

static inline _u32 u2s(_u32 unit)
{
	return _bs_xsfs.n_reserved+_bs_xsfs.n_ss_desc+unit*_bs_xsfs.n_scale;
}

void* read_unit(_u32 unit, _u32 offset)
{
	_u32 n, o;
	n = offset/_bs_xsfs.sector_size;
	o = offset%_bs_xsfs.sector_size;
	if(read_sector(u2s(unit)+n)!=0) return NULL;
	return (char*)_buffer+o;
}

int read_unit_buffer(_u32 unit, _u32 offset, int len, void *buf)
{
	int l1, l2;
	char *p = (char*)read_unit(unit, offset);
	if(!p) return 0;
	l1 = _bs_xsfs.sector_size-(p-(char*)_buffer);
	l2 = l1<len ? len-l1 : 0;
	if(l1>len) l1 = len;
	memcpy(buf, p, l1);
	if(l2)
	{
		p = (char*)read_unit(unit, offset+l1);
		if(!p) return 0;
		memcpy((char*)buf+l1, p, l2);
	}
	return 1;
}

int find_file(_u32 start_unit, const char *filename, XSFSNODE *node)
{
	XSFSBHEAD head;
	XSFSBNODE *pNode;
	_u32 i;
	int c;
	char *p;

	while(start_unit)
	{
		if(!(p = (char*)read_unit(start_unit, 0)))
		{ display(sz_err_disk); return 0; }
		memcpy(&head, p, sizeof(head));
		p += sizeof(XSFSBHEAD);
		for(i=0; i<head.n_total; i++)
		{
			if(_bs_xsfs.sector_size-(p-(char*)_buffer)<sizeof(XSFSBNODE))	// need reload
			{
				p = (char*)read_unit(start_unit, sizeof(XSFSBHEAD)+i*(sizeof(_u32)+sizeof(XSFSNODE)));
				if(!p){ display(sz_err_disk); return 0; }
			}
			pNode = (XSFSBNODE*)p;
			c = strcmp(pNode->node.name, filename);
			if(!(pNode->node.flags&NF_LONGNAME) && c==0)
			{
				memcpy(node, &pNode->node, sizeof(XSFSNODE));
				return 1;
			}
			if(c>0)	// pNode->node.name>filename, search left child in B-tree
			{ start_unit = pNode->b_left; break; }
			else if(c<0 && i==head.n_total)
			{ start_unit = pNode->b_right; break; }
			else p+=sizeof(_u32)+sizeof(XSFSNODE);
		}
	}
	return 0;
}

static inline int get_unit_level(_u32 unit, _u32 index[])
{
	_u32 sec_count = _bs_xsfs.sector_size*_bs_xsfs.n_scale/sizeof(_u32);
	unit -= MAX_PRI_INDEX;
	if(unit<sec_count){ index[0] = unit; return 0; }
	if(unit<sec_count+sec_count*sec_count)
	{ index[0] = (unit-sec_count)/sec_count; index[1] = (unit-sec_count)%sec_count; return 1; }
	index[0] = (unit-sec_count-sec_count*sec_count)/(sec_count*sec_count);
	index[1] = ((unit-sec_count-sec_count*sec_count)%(sec_count*sec_count))/sec_count;
	index[2] = ((unit-sec_count-sec_count*sec_count)%(sec_count*sec_count))%sec_count;
	return 2;
}

void* read_stream(XSFSSTREAM *stream, _u32 pos)
{
	_u32 unit, off, a_unit, u, *p;
	_u32 index[MAX_SEC_INDEX];
	int level, a;

	unit = pos/(_bs_xsfs.sector_size*_bs_xsfs.n_scale);
	off = pos%(_bs_xsfs.sector_size*_bs_xsfs.n_scale);

	if(unit<MAX_PRI_INDEX)
		a_unit = stream->pri_index[unit];
	else
	{
		level = get_unit_level(unit, index);
		for(a=0, u=stream->sec_index[level]; a<=level; a++)
		{
			if(!u){ display("Incorrect position in stream"); return NULL; }
			p = (_u32*)read_unit(u, index[a]*sizeof(_u32));
			if(!p){ display(sz_err_disk); return NULL; }
			u = *p;
		}
		a_unit = u;
	}
	if(!a_unit){ display("Incorrect position in stream"); return NULL; }
	return read_unit(a_unit, off);
}

void _lmemcpy(_u32 des_seg, _u32 des_off, void *buffer, int len)
{
	asm("pushw %%es; movw %%ax, %%es; cld; rep; movsb; popw %%es"
			::"a"(des_seg), "D"(des_off), "S"(buffer), "c"(len));
}

int load_file(XSFSSTREAM *stream, _u32 length, _u32 base)
{
	_u32 l, pos = 0, offset = 0;
	while(length)
	{
		l = min(length, _bs_xsfs.sector_size);
		if(!read_stream(stream, pos))
		{ display(sz_err_disk); return 0; }
		if(offset+l>0xffff)	// exceeds 64K, split
		{
			_lmemcpy(base, offset, _buffer, 0x10000-offset);
			base += 0x1000;
			_lmemcpy(base, 0, (char*)_buffer+0x10000-offset, l+offset-0x10000);
			offset+=l; offset-=0x10000;
		}
		else
		{
			_lmemcpy(base, offset, _buffer, l);
			offset+=l;
		}
		length-=l; pos+=l;
	}
	return 1;
}

void vmain(void)
{
	char buf[1024];	// global buffer
	PARTINFO *pPart;
	XSFSSTREAM *pStream, root_stream, stream;
	XSFSROOT root;
	XSFSNODE node;
	_u32 u, bi, bo;
	char *p;

	display("Stage2...");
	// check media type
	if(_bs_xsfs.sector_size>1024)
	{ display("Unsupported sector size"); return; }

	_buffer = buf;	// global buffer

	// load FSTREE stream
	if(read_sector(_bs_xsfs.n_reserved)!=0)	// ss_desc
	{ display(sz_err_disk); return; }
	pStream = (XSFSSTREAM*)_buffer;
	memcpy(&root_stream, &pStream[SSI_FSTREE], sizeof(root_stream));

	u = root_stream.pri_index[0];
	if(!u)
	{ display("Root entry not found"); return; }

	if(read_sector(u2s(u))!=0)	// root entry
	{ display(sz_err_disk); return; }
	memcpy(&root, _buffer, sizeof(root));

	// find loading-kernel
	if(!find_file(root.root.child_unit, "osknl", &node))
	{ display("osknl is missing"); return; }

	// block offset
	p = (char*)read_stream(&root_stream, root.start_pos + node.data_entry * root.block_size);
	if(!p) return;
	p += sizeof(FSTBLOCK) + sizeof(FSTBLOCKDEF) + FSI_DEFAULT*2*sizeof(_u32);
	bi = ((_u32*)p)[0]; bo = ((_u32*)p)[1];

	// stream of loading-kernel
	p = (char*)read_stream(&root_stream, root.start_pos + bi * root.block_size + bo);
	if(!p) return;
	memcpy(&stream, p+sizeof(FSTBLOCK), sizeof(stream));

	if(!load_file(&stream, node.length, 0x1000)) return;

	display("OK\r\n");
#ifdef __DEBUG__
	dbg0();
#endif
	pPart = (PARTINFO*)buf;
	pPart->l_flags	= _bs_ext;
	pPart->l_loaddx	= _bs_dx;
	pPart->l_part	= _bs_part;
	pPart->l_base	= _bs_base;
	asm("ljmp $0x1000, $0"::"S"(pPart), "c"(sizeof(PARTINFO)));
}

⌨️ 快捷键说明

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