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

📄 boot.c

📁 一个类linux的dos下开发的操作系统.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 32 bytes long */
#define	ELF_PH_LEN		32
/*****************************************************************************
*****************************************************************************/
int check_elf_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_offset)
{
	static const char *format_name = "ELF";
/**/
	unsigned short phtab_ent_size, num_phtab_ents, s, i;
	unsigned long temp, phtab_off;
/* 52 = max of ELF_FILE_HDRLEN (=52) and ELF_PH_LEN (=32) */
	char buf[52];
	sect_t *sect;
	int err;

/* seek to start of kernel within RDSK file */
	lseek(handle, rdsk_offset, SEEK_SET);
/* read 52-byte file header */
	if(read(handle, buf, ELF_FILE_HDRLEN) != ELF_FILE_HDRLEN)
/* short file is not ELF */
		return -ERR_FILE_FORMAT;
/* check if valid ELF and get info */
	if(buf[ELF_FILE_BITNESS] != 1 ||		/* 32-bit */
		buf[ELF_FILE_ENDIAN] != 1 ||		/* little endian */
		buf[ELF_FILE_VER1] != 1)		/* ELF ver 1 */
			return -ERR_FILE_FORMAT;
	if(read_le16(buf + ELF_FILE_TYPE) != 2 ||	/* executable */
		read_le16(buf + ELF_FILE_MACHINE) != 3 || /* i386 */
		read_le32(buf + ELF_FILE_VER2) != 1)	/* ELF ver 1 */
			return -ERR_FILE_FORMAT;
/* the entry point */
	exec->entry_pt = read_le32(buf + ELF_FILE_ENTRY);
/* go to program header table and read it */
	phtab_ent_size = read_le16(buf + ELF_PHTAB_ENTSIZE);
	num_phtab_ents = read_le16(buf + ELF_PHTAB_COUNT);
	phtab_off = read_le32(buf + ELF_PHTAB_OFFSET);
	s = 0;
	for(i = 0; i < num_phtab_ents; i++)
	{
		sect = exec->section + s;
		lseek(handle, phtab_off + phtab_ent_size * i + rdsk_offset,
			SEEK_SET);
		err = read(handle, buf, ELF_PH_LEN);
		if(err != ELF_PH_LEN)
			return -EIO;
		temp = read_le32(buf + ELF_PH_TYPE);
/* choke on 2=DYNAMIC and the forbidden 5=SHLIB segments */
		if(temp == 2 || temp == 5)
			return -ERR_FILE_FORMAT;
/* handle 1=LOAD segment */
		/*else*/ if(temp == 1)
		{
			sect->adr = read_le32(buf + ELF_PH_VIRT_ADR);
			sect->size = read_le32(buf + ELF_PH_SIZE_IN_FILE);
			sect->off = read_le32(buf + ELF_PH_OFFSET);
			temp = read_le32(buf + ELF_PH_FLAGS);
			if(temp & 4)
				sect->read = 1;
			if(temp & 2)
				sect->write = 1;
			if(temp & 1)
				sect->exec = 1;
			sect->load = 1;
			sect->zero = 0;
			sprintf(sect->name, "(%u)", s);
			s++;
/* if size-in-mem>size-in-file, this segment contains the BSS */
			temp = read_le32(buf + ELF_PH_SIZE_IN_MEM);
			if(temp > sect->size)
			{
				sect[1].adr = sect->adr + sect->size;
				sect[1].size = temp - sect->size;
				sect[1].read = sect[1].write =
					sect[1].zero = 1;
				sect[1].exec = sect[1].load = 0;
				sprintf(sect[1].name, "(%u)", s);
				s++;
			}
		}
/* ignore 0=NULL, 6=PHDR, 3=INTERP, and 4=NOTE segments
		else
			nothing; */
	}
	exec->num_sections = s;
	exec->format_name = format_name;
	exec->pmode = 1;
	return 0;
}
/*////////////////////////////////////////////////////////////////////////////
COFF.C - PMODE (32-BIT) DJGPP COFF KERNELS

EXPORTS:
int check_coff_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_offset);
////////////////////////////////////////////////////////////////////////////*/
#include <string.h> /* memcmp(), strcpy() */
#include <stdio.h> /* sprintf() */
/*#include "defs.h"*/

/* 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_AOUT_MAGIC		20	/* 0x010B */
#define	COFF_AOUT_VER		22	/* version stamp */
#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_OFF	40	/* file offset of code */
#define	COFF_AOUT_DATA_OFF	44	/* file offset of data */
/* 48 bytes long */
#define	COFF_FILE_HDRLEN	48

/* COFF section header */
#define	COFF_SECT_NAME		0	/* ".text", ".data", etc. */
#define	COFF_SECT_PHYS_ADR	8	/* physical adr (?) */
#define	COFF_SECT_VIRT_ADR	12	/* load adr (virtual) of section */
#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
/*****************************************************************************
*****************************************************************************/
int check_coff_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_offset)
{
	static const char *format_name = "DJGPP COFF";
/**/
	unsigned short aout_hdr_size;
	unsigned long bss_size;
	unsigned short i;
/* 48 = max of COFF_FILE_HDRLEN(=48) and COFF_SECT_HDRLEN (=40) */
	char buf[48];
	sect_t *sect;
	int err;

/* seek to start of kernel within RDSK file */
	lseek(handle, rdsk_offset, SEEK_SET);
/* read 48-byte file header */
	if(read(handle, buf, COFF_FILE_HDRLEN) != COFF_FILE_HDRLEN)
/* short file is not COFF */
		return -ERR_FILE_FORMAT;
/* check if valid COFF and get info */
	if(read_le16(buf + COFF_FILE_MAGIC) != 0x014C)
		return -ERR_FILE_FORMAT;
	exec->num_sections = read_le16(buf + COFF_FILE_SECT_NUM);
	if(exec->num_sections != 3)	/* .text, .data, .bss */
		return -ERR_FILE_FORMAT;
	aout_hdr_size = read_le16(buf + COFF_FILE_OPTHDR_SIZE);
	if((read_le16(buf + COFF_FILE_FLAGS) & 0x0002) == 0) /* F_EXEC */
		return -ERR_FILE_FORMAT;
	if(read_le16(buf + COFF_AOUT_MAGIC) != 0x010B)
		return -ERR_FILE_FORMAT;
	exec->entry_pt = read_le32(buf + COFF_AOUT_ENTRY);
/* for Win32 PE COFF; must read BSS size from file hdr, not section hdr */
	bss_size = read_le32(buf + COFF_AOUT_BSS_SIZE);
	sect = exec->section;
/* lseek to first section header */
	lseek(handle, rdsk_offset + 20 + aout_hdr_size, SEEK_SET);
	for(i = 0; i < exec->num_sections; i++)
	{
/* read section header */
		err = read(handle, buf, COFF_SECT_HDRLEN);
		if(err != COFF_SECT_HDRLEN)
			return -EIO;
/* code (STYP_TEXT) */
		if(!memcmp(buf + COFF_SECT_NAME, ".text", 5) &&
			(buf[COFF_SECT_FLAGS] & 0xE0) == 0x20)
		{
			sect->load = sect->read = sect->exec = 1;
			sect->zero = sect->write = 0;
			goto FOO;
		}
/* data (STYP_DATA) */
		else if(!memcmp(buf + COFF_SECT_NAME, ".data", 5) &&
			(buf[COFF_SECT_FLAGS] & 0xE0) == 0x40)
		{
			sect->load = sect->read = sect->write = 1;
			sect->zero = sect->exec = 0;
FOO:
			sect->off = read_le32(buf + COFF_SECT_OFF);
			sect->size = read_le32(buf + COFF_SECT_SIZE);
			goto BAR;
		}
/* BSS (STYP_BSS) */
		else if(!memcmp(buf + COFF_SECT_NAME, ".bss", 5) &&
			(buf[COFF_SECT_FLAGS] & 0xE0) == 0x80)
		{
			sect->zero = sect->read = sect->write = 1;
			sect->load = sect->exec = 0;
			sect->off = 0;
			sect->size = bss_size;
BAR:
			sect->adr = read_le32(buf + COFF_SECT_VIRT_ADR);
			strcpy(sect->name, buf + COFF_SECT_NAME);
		}
/* anything else */
		else
			return -ERR_FILE_FORMAT;
		sect++;
	}
	exec->format_name = format_name;
	exec->pmode = 1;
	return 0;
}
/*////////////////////////////////////////////////////////////////////////////
PE.C - PMODE (32-BIT) Win32 PE KERNELS

EXPORTS:
int check_pe_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_offset);
////////////////////////////////////////////////////////////////////////////*/
#include <string.h> /* memcmp() */
/*#include "defs.h"*/
/*****************************************************************************
*****************************************************************************/
int check_pe_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_offset)
{
	static const char *format_name = "Win32 PE";
/**/
	unsigned long new_exe_offset;
	char buf[64];
	int err;

/* seek to start of kernel within RDSK file */
	lseek(handle, rdsk_offset, SEEK_SET);
/* read 64-byte old executable (DOS .EXE) header */
	if(read(handle, buf, 64) != 64)
/* short file is not PE */
		return -ERR_FILE_FORMAT;
	if(memcmp(buf, "MZ", 2) != 0)
		return -ERR_FILE_FORMAT;
	new_exe_offset = read_le32(buf + 60);
	if(new_exe_offset == 0)
		return -ERR_FILE_FORMAT;
/* lseek to and read first 4 bytes of new executable (PE) header */
	lseek(handle, rdsk_offset + new_exe_offset, SEEK_SET);
	if(read(handle, buf, 4) != 4)
		return -ERR_FILE_FORMAT;
	if(memcmp(buf, "PE", 2) != 0)
		return -ERR_FILE_FORMAT;
/* the rest of the file is COFF format */
	err = check_coff_header(exec, handle,
		rdsk_offset + new_exe_offset + 4);
	exec->format_name = format_name;
	return err;
}
/*////////////////////////////////////////////////////////////////////////////
RDSK.C - RDSK-FORMAT INITIAL RAMDISK

EXPORTS:
int check_rdsk_header(exec_t *exec, unsigned handle);
////////////////////////////////////////////////////////////////////////////*/
#include <string.h> /* memcmp() */
/*#include "defs.h"*/

/* IMPORTS:
from BOOT.C */
extern unsigned long _rdsk_file_offset;

/* from other files */
int check_exe_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_file_offset);
int check_elf_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_file_offset);
int check_coff_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_file_offset);
int check_pe_header(exec_t *exec, unsigned handle,
		unsigned long rdsk_file_offset);
/*****************************************************************************
*****************************************************************************/
int check_rdsk_header(exec_t *exec, unsigned handle)
{
	static char buf[32];

/* seek to start of file */
	lseek(handle, 0, SEEK_SET);
/* read 32-byte header */
	if(read(handle, buf, 32) != 32)
		return -ERR_FILE_FORMAT;
/* check if RDSK */
	if(memcmp(buf, "RDSK", 4) != 0)
		return -ERR_FILE_FORMAT;
/* get offset of 0th object (the kernel executable) */
	_rdsk_file_offset = read_le32(buf + 8);
/* check format of kernel */
	if(check_exe_header(exec, handle, _rdsk_file_offset) == 0)
		/* nothing */;
	else if(check_elf_header(exec, handle, _rdsk_file_offset) == 0)
		/* nothing */;
	else if(check_coff_header(exec, handle, _rdsk_file_offset) == 0)
		/* nothing */;
	else if(check_pe_header(exec, handle, _rdsk_file_offset) == 0)
		/* nothing */;
	else
		return -ERR_FILE_FORMAT;
	exec->rdsk = 1;
/* append (RDSK) to format name */
	strcpy(buf, exec->format_name);
	strcat(buf, " (RDSK)");
	exec->format_name = buf;
	return 0;
}
/*////////////////////////////////////////////////////////////////////////////
MAIN.C - CODE TO LOAD AND RUN KERNELS
////////////////////////////////////////////////////////////////////////////*/
#define	BUF_SIZE	4096
#define	to_linear(fp)	(((unsigned long)(FP_SEG(fp)) << 4) + FP_OFF(fp))

/* Check Header Function */
typedef int (*chf_t)(exec_t *exec, unsigned handle,
	unsigned long rdsk_offset);

/* defined in START.ASM */
extern unsigned char _got_32bit_cpu;
extern unsigned long _conv_mem_size, _ext_mem_size;
extern unsigned char _code[], _data[], _bss[], _end[];

unsigned run_pmode_kernel(unsigned long phys_entry_pt);

static unsigned char HUGE *_conv_mem;
static unsigned char _zeroes[BUF_SIZE];
static unsigned long _rdsk_file_offset, _file_size;
/*****************************************************************************
INT 15 - SYSTEM - COPY EXTENDED MEMORY
	AH = 87h
	CX = number of words to copy (max 8000h)
	ES:SI -> global descriptor table (see #00499)
Return: CF set on error
	CF clear if successful
	AH = status (see #00498)
see Ralf Brown's famous Interrupt List for more information

Notes: copy is done in protected mode with interrupts disabled by the
	default BIOS handler; many 386 memory managers perform the
	copy with interrupts enabled

RETURN VALUE:
Values for extended-memory copy status:	(Table 00498)
 00h	source copied into destination
 01h	parity error
 02h	interrupt error
 03h	address line 20 gating failed
 80h	invalid command (PC,PCjr)
 86h	unsupported function (XT,PS30)
*****************************************************************************/
static int copy_extended_memory(unsigned long dst_adr, unsigned long src_adr,
		unsigned short count)
{
/* global descriptor table, from Table 00499 of Ralf Brown's list */
	unsigned char gdt[] =
	{
/* 0 */		0,    0,    0, 0, 0, 0,    0,    0,/* used by BIOS */
/* 8 */		0,    0,    0, 0, 0, 0,    0,    0,/* used by BIOS */

/* page-granular 32-bit data segments with limit 4 Gbytes - 1 */
/* 10h */	0xFF, 0xFF, 0, 0, 0, 0x93, 0xCF, 0,/* src seg */
/* 18h */	0xFF, 0xFF, 0, 0, 0, 0x93, 0xCF, 0,/* dst seg */

/* 20h */	0,    0,    0, 0, 0, 0,    0,    0,/* used by BIOS for CS */
/* 28h */	0,    0,    0, 0, 0, 0,    0,    0/* used by BIOS for SS */
	};
	struct REGPACK regs;

/* fill in src segment descriptor */
	gdt[0x12] = src_adr;
	src_adr >>= 8;
	gdt[0x13] = src_adr;
	src_adr >>= 8;
	gdt[0x14] = src_adr;
	src_adr >>= 8;
	gdt[0x17] = src_adr;
/* fill in dst segment descriptor */
	gdt[0x1A] = dst_adr;
	dst_adr >>= 8;
	gdt[0x1B] = dst_adr;
	dst_adr >>= 8;
	gdt[0x1C] = dst_adr;
	dst_adr >>= 8;
	gdt[0x1F] = dst_adr;
/* call INT 15h AH=87h to copy */
	regs.r_ax = 0x8700;
	count >>= 1;	/* words! */
	regs.r_cx = count;
	regs.r_es = _SS;/* ES:SI -> GDT */
	regs.r_si = (unsigned)gdt;
	intr(0x15, &regs);
/* return status byte from AH. The Borland/Turbo compilers sometimes
screw up shifts. Work-around: put them on their own line of code.
http://www.execpc.com/~geezer/embed/bugs.htm
	return regs.r_ax >> 8; */
	regs.r_ax >>= 8;
	if(regs.r_ax != 0)
	{
		cprintf("\n\rINT 15h AH=87h (copy extended memory) returned "
			"0x%02X\n\r", regs.r_ax);
		return -1;
	}
	return 0;
}
/*****************************************************************************
*****************************************************************************/
static int copy_pmode_section(sect_t *sect, unsigned long virt_to_phys)
{
	unsigned long src, dst, size;
	unsigned short count;
	int err;

	src = to_linear(_conv_mem) + sect->off + _rdsk_file_offset;
	dst = sect->adr + virt_to_phys;
	for(size = sect->size; size != 0; )
	{
		count = (size > 0xFFFE) ? 0xFFFE : size;
		err = copy_extended_memory(dst, src, count);
		if(err != 0)
			return err;
		size -= count;
		src += count;
		dst += count;
	}
	return 0;
}
/*****************************************************************************
*****************************************************************************/
static int zero_pmode_bss(sect_t *sect, unsigned long virt_to_phys)
{
	unsigned long dst, size;
	unsigned short count;

⌨️ 快捷键说明

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