📄 boot.c
字号:
/* 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, ®s);
/* 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 + -