📄 main.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 + -