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

📄 bootimage.c

📁 操作系统加载的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	bootimage.c - Load an image and start it.	Author: Kees J. Bot
 *								19 Jan 1992
 */
#define nil 0
#define _POSIX_SOURCE	1
#define _MINIX		1
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <a.out.h>
#include <minix/config.h>
#include <minix/const.h>
#include <minix/type.h>
#include <kernel/const.h>
#include <kernel/type.h>
#include <ibm/partition.h>
#include "rawfs.h"
#include "image.h"
#include "boot.h"

void printk(char *fmt, ...);
#define	printf	printk

#define click_shift	clck_shft	/* 7 char clash with click_size. */

/* Some kernels have extra features: */
#define K_I386	 0x0001	/* Make the 386 transition before you call me. */
#define K_CLAIM	 0x0002	/* I will acquire my own bss pages, thank you. */
#define K_CHMEM  0x0004	/* This kernel listens to chmem for its stack size. */
#define K_HIGH   0x0008	/* Load mm, fs, etc. in extended memory. */
#define K_HDR	 0x0010	/* No need to patch sizes, kernel uses the headers. */
#define K_RET	 0x0020	/* Returns to the monitor on reboot. */


/* Data about the different processes. */

#define PROCESS_MAX	16	/* Must match the space in kernel/mpx.x */
#define KERNEL		0	/* The first process is the kernel. */
#define FS		2	/* The third must be fs. */

struct process {
	char	name[IM_NAME_MAX + 1]; /* Nice to have a name for the thing. */
	u32_t	entry;		/* Entry point. */
	u32_t	cs;		/* Code segment. */
	u32_t	ds;		/* Data segment. */
	u32_t	data;		/* To access the data segment. */
	u32_t	end;		/* End of this process, size = (end - cs). */
} process[PROCESS_MAX];
int n_procs;			/* Number of processes. */

/* Magic numbers in process' data space. */
#define MAGIC_OFF	0	/* Offset of magic # in data seg. */
#define CLICK_OFF	2	/* Offset in kernel text to click_shift. */
#define FLAGS_OFF	4	/* Offset in kernel text to flags. */
#define KERNEL_D_MAGIC	0x526F	/* Kernel magic number. */

/* Offsets of sizes to be patched into kernel and fs. */
#define P_SIZ_OFF	0	/* Process' sizes into kernel data. */
#define P_INIT_OFF	4	/* Init cs & sizes into fs data. */


#define between(a, c, z)	((unsigned) ((c) - (a)) <= ((z) - (a)))

void pretty_image(char *image)
/* Pretty print the name of the image to load.  Translate '/' and '_' to
 * space, first letter goes uppercase.  An 'r' before a digit prints as
 * 'revision'.  E.g. 'minix/1.6.16r10' -> 'Minix 1.6.16 revision 10'.
 * The idea is that the part before the 'r' is the official Minix release
 * and after the 'r' you can put version numbers for your own changes.
 */
{
	int up= 0, c;

	while ((c= *image++) != 0) {
		if (c == '/' || c == '_') c= ' ';

		if (c == 'r' && between('0', *image, '9')) {
			printf(" revision ");
			continue;
		}
		if (!up && between('a', c, 'z')) c= c - 'a' + 'A';

		if (between('A', c, 'Z')) up= 1;

		putchar(c);
	}
}

void raw_clear(u32_t addr, u32_t count)
/* Clear "count" bytes at absolute address "addr". */
{
	static char zeros[128];
	u32_t dst;
	u32_t zct;

	zct= sizeof(zeros);
	if (zct > count) zct= count;
	raw_copy(addr, mon2abs(&zeros), zct);
	count-= zct;

	while (count > 0) {
		dst= addr + zct;
		if (zct > count) zct= count;
		raw_copy(dst, addr, zct);
		count-= zct;
		zct*= 2;
	}
}

/* Align a to a multiple of n (a power of 2): */
#define align(a, n)	(((u32_t)(a) + ((u32_t)(n) - 1)) & ~((u32_t)(n) - 1))
unsigned click_shift;
unsigned click_size;	/* click_size = Smallest kernel memory object. */
unsigned k_flags;	/* Not all kernels are created equal. */

void patch_sizes(void)
/* Patch sizes of each process into kernel data space, kernel ds into kernel
 * text space, and sizes of init into data space of fs.  All the patched
 * numbers are based on the kernel click size, not hardware segments.
 */
{
	u16_t text_size, data_size;
	int i;
	struct process *procp, *initp;
	u32_t doff;

	if (k_flags & K_HDR) return;	/* Uses the headers. */

	/* Patch text and data sizes of the processes into kernel data space.
	 */
	doff= process[KERNEL].data + P_SIZ_OFF;

	for (i= 0; i < n_procs; i++) {
		procp= &process[i];
		text_size= (procp->ds - procp->cs) >> click_shift;
		data_size= (procp->end - procp->ds) >> click_shift;

		/* Two words per process, the text and data size: */
		put_word(doff, text_size); doff+= 2;
		put_word(doff, data_size); doff+= 2;

		initp= procp;	/* The last process must be init. */
	}

	if (k_flags & K_HIGH) return;	/* Doesn't need FS patching. */

	/* Patch cs and sizes of init into fs data. */
	put_word(process[FS].data + P_INIT_OFF+0, initp->cs >> click_shift);
	put_word(process[FS].data + P_INIT_OFF+2, text_size);
	put_word(process[FS].data + P_INIT_OFF+4, data_size);
}

int selected(char *name)
/* True iff name has no label or the proper label. */
{
	char *colon, *label;
	int cmp;

	if ((colon= strchr(name, ':')) == nil) return 1;
	if ((label= b_value("label")) == nil) return 1;

	*colon= 0;
	cmp= strcmp(label, name);
	*colon= ':';
	return cmp == 0;
}

u32_t proc_size(struct image_header *hdr)
/* Return the size of a process in sectors as found in an image. */
{
	u32_t len= hdr->process.a_text;

	if (hdr->process.a_flags & A_PAL) len+= hdr->process.a_hdrlen;
	if (hdr->process.a_flags & A_SEP) len= align(len, SECTOR_SIZE);
	len= align(len + hdr->process.a_data, SECTOR_SIZE);

	return len >> SECTOR_SHIFT;
}

off_t image_off, image_size;
u32_t (*vir2sec)(u32_t vsec);		/* Where is a sector on disk? */

u32_t file_vir2sec(u32_t vsec)
/* Translate a virtual sector number to an absolute disk sector. */
{
	off_t blk;

	if ((blk= r_vir2abs(vsec / RATIO)) == -1) {
		errno= EIO;
		return -1;
	}
	return blk == 0 ? 0 : lowsec + blk * RATIO + vsec % RATIO;
}

u32_t flat_vir2sec(u32_t vsec)
/* Simply add an absolute sector offset to vsec. */
{
	return lowsec + image_off + vsec;
}

char *get_sector(u32_t vsec)
/* Read a sector "vsec" from the image into memory and return its address.
 * Return nil on error.  (This routine tries to read an entire track, so
 * the next request is usually satisfied from the track buffer.)
 */
{
	u32_t sec;
	int r;
	static char buf[32 * SECTOR_SIZE];
	static size_t count;		/* Number of sectors in the buffer. */
	static u32_t bufsec;		/* First Sector now in the buffer. */

	if (vsec == 0) count= 0;	/* First sector; initialize. */

	if ((sec= (*vir2sec)(vsec)) == -1) return nil;

	if (sec == 0) {
		/* A hole. */
		count= 0;
		memset(buf, 0, SECTOR_SIZE);
		return buf;
	}

	/* Can we return a sector from the buffer? */
	if ((sec - bufsec) < count) {
		return buf + ((size_t) (sec - bufsec) << SECTOR_SHIFT);
	}

	/* Not in the buffer. */
	count= 0;
	bufsec= sec;

	/* Read a whole track if possible. */
	while (++count < 32 && (bufsec + count) % sectors != 0) {
		vsec++;
		if ((sec= (*vir2sec)(vsec)) == -1) break;

		/* Consecutive? */
		if (sec != bufsec + count) break;
	}

	/* Actually read the sectors. */
	if ((r= readsectors(mon2abs(buf), bufsec, count)) != 0) {
		readerr(bufsec, r);
		count= 0;
		errno= 0;
		return nil;
	}
	return buf;
}

int get_clickshift(u32_t ksec, struct image_header *hdr)
/* Get the click shift and special flags from kernel text. */
{
	char *textp;

	if ((textp= get_sector(ksec)) == nil) return 0;

	if (hdr->process.a_flags & A_PAL) textp+= hdr->process.a_hdrlen;
	click_shift= * (u16_t *) (textp + CLICK_OFF);
	k_flags= * (u16_t *) (textp + FLAGS_OFF);

	if (click_shift < HCLICK_SHIFT || click_shift > 16) {
		printf("%s click size is bad\n", hdr->name);
		errno= 0;
		return 0;
	}

	click_size= 1 << click_shift;

	return 1;
}

int get_segment(u32_t *vsec, long *size, u32_t *addr, u32_t limit)
/* Read *size bytes starting at virtual sector *vsec to memory at *addr. */
{
	char *buf;
	size_t cnt, n;

	cnt= 0;
	while (*size > 0) {
		if (cnt == 0) {
			if ((buf= get_sector((*vsec)++)) == nil) return 0;
			cnt= SECTOR_SIZE;
		}
		if (*addr + click_size > limit) { errno= ENOMEM; return 0; }
		n= click_size;
		if (n > cnt) n= cnt;
		raw_copy(*addr, mon2abs(buf), n);
		*addr+= n;
		*size-= n;
		buf+= n;
		cnt-= n;
	}

	/* Zero extend to a click. */
	n= align(*addr, click_size) - *addr;
	raw_clear(*addr, n);
	*addr+= n;
	*size-= n;
	return 1;
}

void exec_image(char *image, char *params, size_t paramsize)
/* Get a Minix image into core, patch it up and execute. */
{
	int i;
	struct image_header hdr;
	char *buf;
	u32_t vsec= 0;		/* Load this sector from image next. */
	u32_t addr= MINIXPOS;	/* Put it at this address. */
	u32_t limit= caddr;	/* But no further than this address. */
	u32_t n;
	struct process *procp;	/* Process under construction. */
	long a_text, a_data, a_bss, a_stack;
	char *msec, *console;
	u16_t mode;
	int banner= 0;
	long processor= a2l(b_value("processor"));

	/* Clear the area where the headers will be placed. */
	raw_clear(HEADERPOS, PROCESS_MAX * A_MINHDR);

	/* Read the many different processes: */
	for (i= 0; vsec < image_size; i++) {
		if (i == PROCESS_MAX) {
			printf("There are more then %d programs in %s\n",
				PROCESS_MAX, image);
			errno= 0;

⌨️ 快捷键说明

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