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

📄 loaderc.c

📁 boot loader bing--boot.asm for fdd and loader c++ -startup.asm
💻 C
📖 第 1 页 / 共 3 页
字号:
/* #include <stdlib.h> malloc() */

static int fat_mount(mount_t *mount, dev_t *dev, unsigned char part)
{
	unsigned char *blk, *ptab_rec; /* partition table record */
	unsigned long total_sectors;
	fat_type_t fat_type;
	fsinfo_t *fsinfo;
	fat_t *fat;
	int err;

	mount->curr_dir = MAGIC_ROOT_CLUSTER;
	dev->bytes_per_sector = BPS;
/* floppy */
	if(dev->int13_dev < 0x80)
	{
		fat_type = FAT12;
/* read sector 0 of floppy (boot sector) */
		mount->partition_start = 0;
		err = read_sector(dev, mount->partition_start, &blk);
		if(err != 0)
			return err;
/* make sure it's a FAT disk */
		if((blk[0] != 0xEB && blk[0] != 0xE9) || /* JMP (SHORT) */
			read_le16(blk + 0x0B) != 512 || /* bytes/sector */
			blk[0x0D] != 1 ||		/* sectors/cluster */
			blk[0x15] != 0xF0 ||		/* media ID */
			blk[0x1A] != 2)			/* heads */
		{
NOT:			cprintf("Partition %u on drive 0x%02X is "
				"not a FAT12 or FAT16 partition\n\r",
				part, dev->int13_dev);
			return -1;
		}
/* read disk geometry from BIOS Parameter Block (BPB) of FAT boot sector */
		dev->sects = read_le16(blk + 0x18);
		dev->heads = read_le16(blk + 0x1A);
	}
/* hard disk */
	else
	{
		if(part > 3)
		{
			cprintf("fat_mount: partition number must be 0-3\n\r");
			return -1;
		}
/* read sector 0 of hard disk (MBR; partition table) */
		err = read_sector(dev, 0, &blk);
		if(err != 0)
			return err;
/* xxx - finish initializing dev */
dev->sects = 63;
dev->heads = 255;
/* point to 16-byte partition table record */
		ptab_rec = blk + 446 + 16 * part;
		switch(ptab_rec[4])
		{
			case 1:
				fat_type = FAT12;
				break;
			case 4:
				fat_type = FAT16; /* up to 32 meg */
				break;
			case 6:
				fat_type = FAT16; /* DOS 3.31+, >32 meg */
				break;
			default:
				goto NOT;
		}
		mount->partition_start = read_le32(ptab_rec + 8);
/* read sector 0 of partition (boot sector) */
		err = read_sector(dev, mount->partition_start, &blk);
		if(err != 0)
			return err;
/* make sure it's a FAT disk */
		if((blk[0] != 0xEB && blk[0] != 0xE9) || /* JMP (SHORT) */
			read_le16(blk + 0x0B) != 512)	/* bytes/sector */
				goto NOT;
	}
/*	fat = malloc(sizeof(fat_t));
	if(fat == NULL)
		return ERR_MEM; */
	mount->dev = dev;
/* init mount->fsinfo */
	fsinfo = &mount->fsinfo;
fat = (fat_t *)fsinfo->info;

	fsinfo->open_root = fat_open_root;
	fsinfo->readdir = fat_readdir;
	fsinfo->read = fat_read;
/* init mount->fsinfo->info
	fsinfo->info = fat; */
memcpy(fsinfo->info, fat, sizeof(fat));
	fat = (fat_t *)fsinfo->info;
	fat->sectors_per_cluster = blk[13];
	fat->fat_start = read_le16(blk + 14);	/* reserved_sectors */
	fat->root_start = fat->fat_start +
		blk[16] *			/* num_fats */
		read_le16(blk + 22);		/* sectors_per_fat */
	fat->data_start = fat->root_start +
		(FAT_DIRENT_LEN *		/* bytes_per_dir_ent */
		read_le16(blk + 17)) /		/* num_root_dir_ents */
			BPS;			/* bytes_per_sector */
	total_sectors = read_le16(blk + 19);
	if(total_sectors == 0)
		total_sectors = read_le32(blk + 32);
	fat->max_cluster = total_sectors /
		fat->sectors_per_cluster -
		fat->data_start - 1;
	fat->fat_type = fat_type;
#if 0
cprintf("disk CHS=??:%u:%u\n\r", dev->heads, dev->sects);

cprintf("drive 0x%02X, partition %u: %s partition starting at sector %lu\n\r",
dev->int13_dev, part, fat->fat_type == FAT12 ? "FAT12" : "FAT16",
mount->partition_start);

cprintf("%u sector(s)/cluster, ", fat->sectors_per_cluster);
cprintf("%u FATs, ", blk[0x10]);
cprintf("root at sector %lu, ", fat->root_start);
cprintf("data at sector %lu\n\r", fat->data_start);

cprintf("FAT(s) at sector %lu, ", fat->fat_start);
cprintf("%u entries in root dir, ", read_le16(blk + 0x11));
cprintf("%lu total sectors ", total_sectors);
if(total_sectors >= 16384)
	cprintf("(%luM)\n\r\n\r", total_sectors / 2048);
else
	cprintf("(%luK)\n\r\n\r", total_sectors / 2);
#endif
	return 0;
}
/*////////////////////////////////////////////////////////////////////////////
	VFS
////////////////////////////////////////////////////////////////////////////*/
/*****************************************************************************
read directory entry from directory 'dir'
stores entry at 'file' (we use file_t instead of a DIR type)
*****************************************************************************/
static int my_readdir(file_t *dir, file_t *file)
{
	fsinfo_t *fsinfo;
	mount_t *mount;

	mount = dir->mount;
	fsinfo = &mount->fsinfo;
	return fsinfo->readdir(dir, file);
}
/*****************************************************************************
find file 'name' in already-opened directory 'dir';
stores result at 'file' if success
*****************************************************************************/
static int my_find(file_t *dir, file_t *file, char *name)
{
	int err;

/* seek to beginning of dir */
	err = my_seek(dir, 0, SEEK_SET);
	if(err != 0)
		return err;
/* read one 32-byte directory entry */
	do
	{
		err = my_readdir(dir, file);
		if(err != 0)
			return err;
	} while(strcmp(name, file->name));
	return 0;
}
/*****************************************************************************
convert path from relative to absolute, if necessary?
remove superfluous components of path (e.g. /./ )?
figure out mount point based on absolute path?
*****************************************************************************/
static int my_open(file_t *file, char *path)
{
	char done = 0, *slash;
	file_t search_dir;
	fsinfo_t *fsinfo;
	mount_t *mount;
	int err;

	file->mount = mount = &_mount;
	fsinfo = &mount->fsinfo;
	if(path[0] == '/')
	{
/* skip first '/' */
		path++;
/* open root dir */
		err = fsinfo->open_root(&search_dir, mount);
		if(err != 0)
			return err;
/* done already? */
		if(path[0] == '\0')
		{
			memcpy(file, &search_dir, sizeof(file_t));
			return 0;
		}
	}
/* xxx - relative pathnames are not yet handled */
	else
		return -1;
	done = 0;
	do
	{
/* pick out one name in path */
		slash = strchr(path, '/');
		if(slash == NULL)
		{
			slash = path + strlen(path);
			done = 1;
		}
		*slash = '\0';
/* find file/dir of this name in search_dir */
		err = my_find(&search_dir, file, path);
		if(err != 0)
		{
			my_close(&search_dir);
			return err;
		}
		if(done)
			break;
/* CD to subdirectory */
		memcpy(&search_dir, file, sizeof(file_t));
/* advance to next name+ext pair in pathname
+1 to skip '/' */
		path = slash + 1;
	} while(path[0] != '\0');
	return 0;
}
/*****************************************************************************
*****************************************************************************/
static int my_read(file_t *file, void *buf, unsigned len)
{
	fsinfo_t *fsinfo;
	mount_t *mount;

	mount = file->mount;
	fsinfo = &mount->fsinfo;
	return fsinfo->read(file, buf, len);
}
/*****************************************************************************
*****************************************************************************/
static int my_seek(file_t *file, long offset, int whence)
{
	switch(whence)
	{
		case SEEK_SET:
			/* nothing */
			break;
		case SEEK_CUR:
			offset += file->pos;
			break;
		case SEEK_END:
			offset = (file->file_size - 1) - offset;
			break;
		default:
			return -1;
	}
	if(offset < 0)
		offset = 0;
	else if(offset >= file->file_size - 1)
		offset = file->file_size - 1;
	file->pos = offset;
	return 0;
}
/*****************************************************************************
*****************************************************************************/
#pragma argsused
static int my_close(file_t *file)
{
	return 0;
}
/*////////////////////////////////////////////////////////////////////////////
	CONSOLE ROUTINES
////////////////////////////////////////////////////////////////////////////*/
#include <stdarg.h> /* va_list, va_start(), va_end() */
#include <string.h> /* strlen() */
#include <dos.h> /* struct REGPACK, intr() */
/* note that Turbo C 2.0 intr() is buggy (doesn't load register BP properly),
so I've written my own version in LOADERA.ASM */

int vsprintf(char *, const char *, void *);

static unsigned char _attrib = 0x07; /* white on black */
/*****************************************************************************
*****************************************************************************/
static void gotoxy(unsigned char x, unsigned char y)
{
	struct REGPACK regs;

	regs.r_dx = y;
	regs.r_dx <<= 8;
	regs.r_dx |= x;
	regs.r_bx = 0;		/* BH=video page 0 */
	regs.r_ax = 0x0200;	/* AH=subfunction 2 (move csr) */
	intr(0x10, &regs);
}
/*****************************************************************************
*****************************************************************************/
static void textattr(int a)
{
	_attrib = a;
}
/*****************************************************************************
*****************************************************************************/
static void cprintf(const char *fmt, ...)
{
	struct REGPACK regs;
	char buf[200];
	va_list args;

	va_start(args, fmt);
	vsprintf(buf, fmt, args);
	va_end(args);

	regs.r_bx = 0;		/* BH=video page 0 */
	regs.r_ax = 0x0300; /* AH=subfunction 3: get cursor pos to DH,DL */
	intr(0x10, &regs);

	regs.r_es = _DS;
	regs.r_bp = (unsigned)buf;
	regs.r_cx = strlen(buf);
	regs.r_bx = _attrib;	/* BH=video page 0, BL=attribute */
	regs.r_ax = 0x1301;	/* AH=subfunction 13h, AL=write mode 1 */
	intr(0x10, &regs);
}
/*****************************************************************************
*****************************************************************************/
static int getch(void)
{
	static short prev = -1;
	struct REGPACK regs;
	int ret_val;

	if(prev != -1)
	{
		ret_val = prev;
		prev = -1;
	}
	else
	{
		regs.r_ax = 0; /* AH=subfunction 0 (get key) */
		intr(0x16, &regs);
		ret_val = regs.r_ax & 0xFF;
		if(ret_val == 0)
		{
			regs.r_ax >>= 8;
			prev = regs.r_ax;
		}
	}
	return ret_val;
}
/*****************************************************************************
*****************************************************************************/
static void erase_screen(unsigned char x, unsigned char y,
		unsigned char wd, unsigned char ht)
{
	struct REGPACK regs;

	regs.r_ax = 0x0600;	/* AH=subfunction 6 (scroll), AH=0 (erase) */
	regs.r_bx = _attrib;
	regs.r_bx <<= 8;	/* BH=attribute */
	regs.r_cx = y;
	regs.r_cx <<= 8;	/* CH=row */
	regs.r_cx |= x;		/* CL=col */
	regs.r_dx = (y + ht - 1);
	regs.r_dx <<= 8;	/* DH=height */
	regs.r_dx |= (x + wd - 1);/* DL=width */
	intr(0x10, &regs);
}
/*////////////////////////////////////////////////////////////////////////////
	KERNEL FILES
////////////////////////////////////////////////////////////////////////////*/
#define	MAX_SECT	4

typedef struct		/* section in executable file */
{
	char sect_name[12];
	unsigned long adr, size, off;
/* section flags */
	unsigned bss : 1;
	unsigned read : 1;
	unsigned write : 1;
	unsigned exec : 1;
} sect_t;

typedef struct		/* entire executable file */
{
	unsigned long entry_pt;
	unsigned short num_sections;
	sect_t section[MAX_SECT];
	char format_name[32];
	unsigned pmode : 1;
	unsigned cosmos : 1;
} exec_t;
/*****************************************************************************
returns -1 if file is not COFF,
returns ERR_FILE if invalid COFF file,
*****************************************************************************/
/* COFF file header */
#define	COFF_FILE_MAGIC		0	/* 0x014C */
#define	COFF_FILE_SECT_NUM	2	/* number of sections */
#define	COFF_FILE_TIMEDATE	4	/* time and date stamp */
#define	COFF_FILE_SYMTAB_OFF	8	/* file offset of symbol table */
#define	COFF_FILE_SYMTAB_NUM	12	/* number of symtab entries */
#define	COFF_FILE_OPTHDR_SIZE	16	/* "optional" (aout) header size */
#define	COFF_FILE_FLAGS		18
/* 20 bytes to here */
#define	COFF_FILE_HDRLEN	20

#define	COFF_AOUT_MAGIC		20	/* 0x010B */
#define	COFF_AOUT_VER		22
#define	COFF_AOUT_CODE_SIZE	24
#define	COFF_AOUT_DATA_SIZE	28
#define	COFF_AOUT_BSS_SIZE	32
#define	COFF_AOUT_ENTRY		36	/* initial EIP */
#define	COFF_AOUT_CODE_BASE	40
#define	COFF_AOUT_DATA_BASE	44
/* 48 bytes to here */
#define	AOUT_FILE_HDRLEN	48

/* COFF section header */
#define	COFF_SECT_NAME		0	/* ".text", ".data", etc. */
#define	COFF_SECT_PADR		8	/* physical adr */
#define	COFF_SECT_VADR		12	/* virtual adr */
#define	COFF_SECT_SIZE		16
#define	COFF_SECT_OFF		20	/* file offset of section */
#define	COFF_SECT_RELOC_OFF	24	/* file offset of relocations */
#define	COFF_SECT_LINENUM_OFF	28	/* file offset of line number info */
#define	COFF_SECT_RELOC_NUM	32	/* number of relocations */
#define	COFF_SECT_LINENUM_NUM	34	/* number of line numbers */
#define	COFF_SECT_FLAGS		36
/* 40 bytes long */
#define	COFF_SECT_HDRLEN	40

static int read_coff_file(exec_t *exec, file_t *file, unsigned long offset)
{
	unsigned char file_hdr[AOUT_FILE_HDRLEN], sect_hdr[COFF_SECT_HDRLEN];
	unsigned short aout_hdrlen, i;
	sect_t *sect;
	int temp;

	(void)my_seek(file, offset, SEEK_SET);
/* read file header and a.out header */
	temp = my_read(file, file_hdr, AOUT_FILE_HDRLEN);
	if(temp < 0)
		return temp;
/* short file is not a COFF file
return -1 instead of ERR_FILE */
	if(temp != AOUT_FILE_HDRLEN)
		return -1;
	if(read_le16(file_hdr + COFF_FILE_MAGIC) != 0x014C)
		return -1;
/* OK, it's COFF. Check for 3 sections (.text, .data, .bss) */
	exec->num_sections = read_le16(file_hdr + COFF_FILE_SECT_NUM);
	if(exec->num_sections != 3)
	{
ERR:		cprintf("invalid COFF file");
/* oops, I thought it was COFF... */
		return ERR_FILE;
	}
/* check flags for F_EXEC */
	if((read_le16(file_hdr + COFF_FILE_FLAGS) & 0x0002) == 0)
		goto ERR;
	if(read_le16(file_hdr + COFF_AOUT_MAGIC) != 0x010B)
		goto ERR;
	aout_hdrlen = read_le16(file_hdr + COFF_FILE_OPTHDR_SIZE);
	exec->entry_pt = read_le32(file_hdr + COFF_AOUT_ENTRY);
/* skip to first section */
	my_seek(file, offset + COFF_FILE_HDRLEN + aout_hdrlen, SEEK_SET);
	sect = exec->section;
	for(i = 0; i < exec->num_sections; i++)
	{
/* read section header */
		temp = my_read(file, sect_hdr, COFF_SECT_HDRLEN);
		if(temp != COFF_SECT_HDRLEN)
			goto ERR;
/* code; STYP_TEXT */
		if(!memcmp(sect_hdr + COFF_SECT_NAME, ".text", 5) &&
			(read_le32(sect_hdr + COFF_SECT_FLAGS) & 0xE0) == 0x20)
		{
			sect->exec = 1;
			sect->size = read_le32(sect_hdr + COFF_SECT_SIZE);
		}
/* data; STYP_DATA */
		else if(!memcmp(sect_hdr + COFF_SECT_NAME, ".data", 5) &&
			(read_le32(sect_hdr + COFF_SECT_FLAGS) & 0xE0) == 0x40)
		{
			sect->write = 1;
			sect->size = read_le32(sect_hdr + COFF_SECT_SIZE);
		}
/* BSS; STYP_BSS */
		else if(!memcmp(sect_hdr + COFF_SECT_NAME, ".bss", 5) &&
			(read_le32(sect_hdr + COFF_SECT_FLAGS) & 0xE0) == 0x80)
		{
			sect->bss = 1;
			sect->write = 1;
			sect->size = read_le32(file_hdr + COFF_AOUT_BSS_SIZE);
/*			sect->size = read_le32(sect_hdr + COFF_SECT_SIZE);*/
		}
/* anything else */
		else
		{
			cprintf("bad section '%-8.8s' in COFF file",
				(char *)sect_hdr + COFF_SECT_NAME);
			return ERR_FILE;
		}
		sect->read = 1;
		strcpy(sect->sect_name, (char *)sect_hdr + COFF_SECT_NAME);
		sect->off = read_le32(sect_hdr + COFF_SECT_OFF);
/*		sect->adr = read_le32(sect_hdr + COFF_SECT_PADR); */
		sect->adr = read_le32(sect_hdr + COFF_SECT_VADR);
		sect++;
	}
	strcpy(exec->format_name, "DJGPP COFF");
	exec->pmode = 1;
	return 0;
}
/*****************************************************************************
returns -1 if file is not PE,
returns ERR_FILE if invalid PE file,
*****************************************************************************/
static int read_pe_file(exec_t *exec, file_t *file, unsigned long offset)
{
	unsigned long new_exe_offset;
	unsigned char buf[64];
	int temp;

	(void)my_seek(file, offset, SEEK_SET);
/* read DOS "MZ" EXE file header */
	temp = my_read(file, buf, 64);
	if(temp < 0)
		return temp;
/* short file is not a PE file
return -1 instead of temp_FILE */

⌨️ 快捷键说明

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