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

📄 boot.c

📁 boot启动监视代码 boot启动监视代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	boot 1.5.4 - Load and start Minix.		Author: Kees J. Bot */char version[]=		"1.5";#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/partition.h>#include <minix/boot.h>#include <minix/type.h>#include <kernel/const.h>#include <kernel/type.h>#include "rawfs.h"#undef EXTERN#define EXTERN	/* Empty */#include "boot.h"#define arraysize(a)	(sizeof(a) / sizeof((a)[0]))#define arraylimit(a)	((a) + arraysize(a))#define	printf	printkchar *bios_err(err) int err;/* Translate BIOS error code to a readable string.  (This is a rare trait * known as error checking and reporting.  Take a good look at it, you won't * see it often.) */{	static struct errlist {		unsigned char	err;		char		*what;	} errlist[] = {		{ 0x00, "No error" },		{ 0x01, "Invalid command" },		{ 0x02, "Address mark not found" },		{ 0x03, "Disk write-protected" },		{ 0x04, "Sector not found" },		{ 0x05, "Reset failed" },		{ 0x06, "Floppy disk removed" },		{ 0x07, "Bad parameter table" },		{ 0x08, "DMA overrun" },		{ 0x09, "DMA crossed 64 KB boundary" },		{ 0x0A, "Bad sector flag" },		{ 0x0B, "Bad track flag" },		{ 0x0C, "Media type not found" },		{ 0x0D, "Invalid number of sectors on format" },		{ 0x0E, "Control data address mark detected" },		{ 0x0F, "DMA arbitration level out of range" },		{ 0x10, "Uncorrectable CRC or ECC data error" },		{ 0x11, "ECC corrected data error" },		{ 0x20, "Controller failed" },		{ 0x40, "Seek failed" },		{ 0x80, "Disk timed-out" },		{ 0xAA, "Drive not ready" },		{ 0xBB, "Undefined error" },		{ 0xCC, "Write fault" },		{ 0xE0, "Status register error" },		{ 0xFF, "Sense operation failed" }	};	struct errlist *errp;	for (errp= errlist; errp < arraylimit(errlist); errp++)		if (errp->err == err) return errp->what;	return "Unknown error";}char *unix_err(err) int err;/* Translate the few errors rawfs can give. */{	switch (err) {	case ENOENT:	return "No such file or directory";	case ENOTDIR:	return "Not a directory";	default:	return "Unknown error";	}}void rwerr(rw, sec, err) char *rw; off_t sec; int err;{	printf("\n%s error 0x%02x (%s) at sector %ld absolute\n",		rw, err, bios_err(err), sec);}void readerr(sec, err) off_t sec; int err;	{ rwerr("Read", sec, err); }void writerr(sec, err) off_t sec; int err;	{ rwerr("Write", sec, err); }/* Readblock support for rawfs.c */#define CACHE_SIZE	32	/* More than enough. */int cache_live= 0;struct cache_entry {	u32_t	block;	u16_t	seg;} cache[CACHE_SIZE];void init_cache()/* Initialize the block cache. */{	struct cache_entry *pc;	u16_t seg= FREESEG;	for (pc= cache; pc < arraylimit(cache); pc++) {		pc->block= -1;		pc->seg= seg;		seg+= BLOCK_SIZE/HCLICK_SIZE;	}	cache_live= 1;	/* Turn it on. */}void invalidate_cache()/* The cache can't be used when Minix is loaded. */{	cache_live= 0;}void readblock(blk, buf) off_t blk; char *buf;/* Read blocks for the rawfs package with caching.  Wins 2 seconds. */{	int r= 0;	u32_t sec= lowsec + blk * RATIO;	if (!cache_live) {		/* Cache invalidated, load block directly in place. */		r= readsectors((u16_t) buf, dseg, sec, 1 * RATIO);	} else {		/* Search through the cache from 0 up.  Move the one found		 * to the front of the cache, then optionally read a block.		 */		struct cache_entry *pc, lifo, tmp;		for (pc= cache; pc < arraylimit(cache); pc++) {			tmp= *pc;			*pc= lifo;			lifo= tmp;			if (lifo.block == blk) break;		}		cache[0]= lifo;		if (cache[0].block != blk) {			r= readsectors(0, cache[0].seg, sec, 1 * RATIO);			cache[0].block= blk;		}		raw_copy((u16_t) buf, dseg, 0, cache[0].seg, BLOCK_SIZE);	}	if (r != 0) { readerr(sec, r); reboot(); }}char *readline()/* Read a line including a newline with echoing. */{	char *line;	size_t i= 0, z;	int c;	line= (char *) malloc((z= 20) * sizeof(char));	do {		c= getchar();		if (strchr("\b\177\25\30", c) != nil) {			/* Backspace, DEL, ctrl-U, or ctrl-X. */			do {				if (i == 0) break;				printf("\b \b");				i--;			} while (c == '\25' || c == '\30');		} else		if (c < ' ' && c != '\n')			putchar('\7');		else {			putchar(c);			line[i++]= c;			if (i == z) line= (char *) realloc((void *) line,						(z*= 2) * sizeof(char));		}	} while (c != '\n');	line[i]= 0;	return line;}int sugar(tok) char *tok;/* Recognize special tokens. */{	return strchr("=(){};\n", tok[0]) != nil;}char *onetoken(aline, arg) char **aline; int arg;/* Returns a string with one token for tokenize.  Arg is true when reading * between ( and ). */{	char *line= *aline;	size_t n;	char *tok;	/* Skip spaces. */	while (*line == ' ') line++;	*aline= line;	/* Don't do odd junk (nor the terminating 0!). */	if ((unsigned) *line < ' ' && *line != '\n') return nil;	if (arg) {		/* Function argument, anything goes except ). */		int depth= 0;		while ((unsigned) *line >= ' ') {			if (*line == '(') depth++;			if (*line == ')' && --depth < 0) break;			line++;		}		while (line > *aline && line[-1] == ' ') line--;	} else	if (sugar(line)) {		/* Single character token. */		line++;	} else {		/* Multicharacter token. */		do line++; while ((unsigned) *line > ' ' && !sugar(line));	}	n= line - *aline;	tok= (char *) malloc((n + 1) * sizeof(char));	memcpy((void *) tok, (void *) *aline, n);	tok[n]= 0;	if (tok[0] == '\n') tok[0]= ';';	/* ';' same as '\n' */	*aline= line;	return tok;}/* Typed commands form strings of tokens. */typedef struct token {	struct token	*next;	/* Next in a command chain. */	char		*token;} token;token **tokenize(acmds, line, fundef)	token	**acmds;	/* Splice tokenized line into this list. */	char	*line;		/* Characters to be tokenized. */	int	*fundef;	/* Keeps state when forming a function def. *//* Takes a line apart to form tokens.  The tokens are inserted into a command * chain at *acmds.  Tokenize returns a reference to where another line could * be added.  The fundef variable holds the state tokenize is in when decoding * a multiline function definition.  It is nonzero when more must be read. * Tokenize looks at spaces as token separators, and recognizes only * ';', '=', '(', ')' '{', '}', and '\n' as single character tokens. */{	int fd= *fundef;	char *tok;	token *newcmd;	static char funsugar[]= { '(', 0, ')', '{', '}' };	while ((tok= onetoken(&line, fd == 1)) != nil) {		if (fd == 1)			fd++;	/* Function argument. */		else		if (funsugar[fd] == tok[0]) {			/* Recognize next token as part of a function def. */			fd= tok[0] == '}' ? 0 : fd + 1;		} else		if (fd != 0) {			if (tok[0] == ';' && fd == 3) {				/* Kill separator between ')' and '{'. */				free((void *) tok);				continue;			}			/* Syntax error unless between '{' and '}'. */			if (fd != 4) fd= 0;		}		newcmd= (token *) malloc(sizeof(*newcmd));		newcmd->token= tok;		newcmd->next= *acmds;		*acmds= newcmd;		acmds= &newcmd->next;	}	*fundef= fd;	return acmds;}token *cmds;		/* String of commands to execute. */char *poptoken()/* Pop one token off the command chain. */{	token *cmd= cmds;	char *tok= cmd->token;	cmds= cmd->next;	free((void *) cmd);	return tok;}void voidtoken()/* Remove one token from the command chain. */{	free((void *) poptoken());}void void_cmds()/* Void the whole list. */{	while (cmds != nil) voidtoken();}void interrupt()/* Clean up after an ESC has been typed. */{	printf("[ESC]\n");	while (peekchar() == ESC) (void) getchar();	/* Delete leftover commands. */	void_cmds();}struct biosdev {	int device, primary, secondary;} bootdev, tmpdev;int activate;struct part_entry boot_part;char dskpars[DSKPARSIZE]=	/* 360K floppy disk parameters (for now). */	{ 0xDF, 0x02, 25, 2,  9, 0x2A, 0xFF, 0x50, 0xF6, 15, 8 };void migrate()/* Copy boot program to the far end of memory, this must be done asap to * put the data area cleanly inside a 64K chunk (no DMA problems). */{	u16_t oldseg= cseg;	u16_t size= (runsize + HCLICK_SIZE - 1) >> HCLICK_SHIFT;	u16_t memsize= get_low_memsize() * (1024 / HCLICK_SIZE);	u16_t dma64k= (memsize - 1) & 0xF000;	u16_t newseg= memsize - size;	vector dskbase;	/* Check if data segment crosses a 64k boundary. */	if (newseg + (dseg - cseg) < dma64k) newseg= dma64k - size;	/* Get some variables into my address space before they get mashed. */	if (device < 0x80) {		/* Floppy disk parameters. */		raw_copy((u16_t) &dskbase, dseg,			(u16_t) (DSKBASE * sizeof(vector)), 0, sizeof(vector));		raw_copy((u16_t) dskpars, dseg,			dskbase.offset, dskbase.segment, DSKPARSIZE);	} else {		/* Hard disk partition table entry into boot_part. */		raw_copy((u16_t) &boot_part, dseg, rem_part.offset,					rem_part.segment, sizeof(boot_part));	}	/* Set the new cseg for relocate. */	cseg= newseg;	/* Copy code and data in large chunks. */	do {		u16_t chunk= size < 0x0FFF ? size : 0x0FFF;		raw_copy(0, newseg, 0, oldseg, chunk << HCLICK_SHIFT);		oldseg+= chunk;		newseg+= chunk;		size-= chunk;	} while (size > 0);	relocate();	/* Make the copy running. */	/* Set the parameters for the boot device using global variables	 * device and dskpars.  (This particular call should not fail.)	 */	(void) dev_geometry();}int get_master(master, table, pos)	char *master;	struct part_entry **table;	u32_t pos;/* Read a master boot sector and its partition table. */{	int r, n;	struct part_entry *pe, **pt;	if ((r= readsectors((u16_t) master, dseg, pos, 1)) != 0) return r;	pe= (struct part_entry *) (master + PART_TABLE_OFF);	for (pt= table; pt < table + NR_PARTITIONS; pt++) *pt= pe++;	/* DOS has the misguided idea that partition tables must be sorted. */	if (pos != 0) return 0;		/* But only the primary. */	n= NR_PARTITIONS;	do {		for (pt= table; pt < table + NR_PARTITIONS-1; pt++) {			if (pt[0]->sysind == NO_PART				|| (pt[0]->lowsec > pt[1]->lowsec						&& pt[1]->sysind != NO_PART)) {				pe= pt[0]; pt[0]= pt[1]; pt[1]= pe;			}		}	} while (--n > 0);	return 0;}void initialize(){	char master[SECTOR_SIZE];	struct part_entry *table[NR_PARTITIONS];	int r, p;	u32_t masterpos;	/* Find out what the boot device and partition was. */	bootdev.device= device;	bootdev.primary= -1;	bootdev.secondary= -1;	if (device < 0x80) return;	/* Get the partition table from the very first sector, and determine	 * the partition we booted from.  Migrate() was so nice to put the	 * partition table entry of the booted partition in boot_part.	 */	/* The only thing really needed from the booted partition: */	lowsec= boot_part.lowsec;	masterpos= 0;	/* Master bootsector position. */	for (;;) {		/* Extract the partition table from the master boot sector. */		if ((r= get_master(master, table, masterpos)) != 0) {			readerr(masterpos, r); reboot();		}		/* See if you can find "lowsec" back. */		for (p= 0; p < NR_PARTITIONS; p++)			if (lowsec - table[p]->lowsec < table[p]->size) break;		if (lowsec == table[p]->lowsec) {	/* Found! */			if (bootdev.primary < 0)

⌨️ 快捷键说明

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