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

📄 boot.c

📁 操作系统引导监控程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		active->bootind= ACTIVE_FLAG;
		dirty= 1;
	}

	/* Read the boot sector. */
	if ((r= readsectors(BOOTPOS, active->lowsec, 1)) != 0) return r;

	/* Check signature word. */
	if (get_word(BOOTPOS+SIGNATOFF) != SIGNATURE) return B_NOSIG;

	/* Write the partition table if a member must be made active. */
	if (dirty && (r= writesectors(mon2abs(master), masterpos, 1)) != 0)
		return r;

	bootstrap(device, active);
}

void boot_device(char *devname)
/* Boot the device named by devname. */
{
	dev_t dev= name2dev(devname);
	int save_dev= device;
	int r;

	if (tmpdev.device < 0) {
		if (dev != -1) printf("Can't boot from %s\n", devname);
		return;
	}

	switch (r= exec_bootstrap(dev)) {
	case B_NODEV:
		printf("%s: device not present\n", devname);
		break;
	case B_NOSIG:
		printf("%s is not bootable\n", devname);
		break;
	default:
		printf("Can't boot %s: %s\n", devname, bios_err(r));
	}

	/* Restore boot device setting. */
	device= save_dev;
	(void) dev_geometry();
}

#else /* DOS */

void boot_device(char *devname)
/* No booting of other devices under DOS */
{
	printf("Can't boot devices under MS-DOS\n");
}
#endif /* DOS */

void ls(char *dir)
/* List the contents of a directory. */
{
	ino_t ino;
	struct stat st;
	char name[NAME_MAX+1];

	if (!fsok) return;

	if ((ino= r_lookup(ROOT_INO, dir)) == 0
		|| (r_stat(ino, &st), r_readdir(name)) == -1
	) {
		printf("ls: %s: %s\n", dir, unix_err(errno));
		return;
	}
	(void) r_readdir(name);	/* Skip ".." too. */

	while ((ino= r_readdir(name)) != 0) printf("%s/%s\n", dir, name);
}

u32_t milli_time(void)
{
	return get_tick() * MSEC_PER_TICK;
}

u32_t milli_since(u32_t base)
{
	return (milli_time() + (TICKS_PER_DAY*MSEC_PER_TICK) - base)
			% (TICKS_PER_DAY*MSEC_PER_TICK);
}

char *Thandler;
u32_t Tbase, Tcount;

void unschedule(void)
/* Invalidate a waiting command. */
{
	if (Thandler != nil) {
		free(Thandler);
		Thandler= nil;
	}
}

void schedule(long msec, char *cmd)
/* Schedule command at a certain time from now. */
{
	unschedule();
	Thandler= cmd;
	Tbase= milli_time();
	Tcount= msec;
}

int expired(void)
/* Check if the timer expired.  If so prepend the scheduled command to
 * the command chain and return 1.
 */
{
	int fundef= 0;

	if (Thandler == nil || milli_since(Tbase) < Tcount) return 0;

	(void) tokenize(tokenize(&cmds, Thandler, &fundef), ";", &fundef);
	unschedule();
	return 1;
}

int delay(char *msec)
/* Delay for a given time.  Returns true iff delay was not interrupted.
 * Make sure no time functions are used if msec == 0, because get_tick()
 * may do funny things on the original IBM PC (not the XT!).
 * If msec happens to be the string "swap" then wait till the user hits
 * return after changing diskettes.
 */
{
	int swap= 0;
	u32_t base, count;

	if (strcmp(msec, "swap") == 0) {
		swap= 1;
		count= 0;
		printf("\nInsert the root diskette then hit RETURN\n");
	} else
	if ((count= a2l(msec)) > 0) {
		base= milli_time();
	}

	do {
		switch (peekchar()) {
		case -1:	break;
		case ESC:	interrupt(); return 0;
		case '\n':	swap= 0;
		default:	(void) getchar();
		}
	} while (!expired()
		&& (swap || (count > 0 && milli_since(base) < count))
	);
	return 1;
}

enum whatfun { NOFUN, SELECT, DEFFUN, USERFUN } menufun(environment *e)
{
	if (!(e->flags & E_FUNCTION) || e->arg[0] == 0) return NOFUN;
	if (e->arg[1] != ',') return SELECT;
	return e->flags & E_RESERVED ? DEFFUN : USERFUN;
}

void menu(void)
/* By default:  Show a simple menu.
 * Multiple kernels/images:  Show extra selection options.
 * User defined function:  Kill the defaults and show these.
 * Wait for a keypress and execute the given function.
 */
{
	int fundef= 0, c, def= 1;
	char *choice= nil;
	environment *e;

	/* Just a default menu? */
	for (e= env; e != nil; e= e->next) if (menufun(e) == USERFUN) def= 0;

	printf("\nHit a key as follows:\n\n");

	/* Show the choices. */
	for (e= env; e != nil; e= e->next) {
		switch (menufun(e)) {
		case DEFFUN:
			if (!def) break;
			/*FALL THROUGH*/
		case USERFUN:
			printf("    %c  %s\n", e->arg[0], e->arg+2);
			break;
		case SELECT:
			printf("    %c  Select %s kernel\n", e->arg[0],e->name);
		}
	}

	/* Wait for a keypress. */
	do {
		while (peekchar() == -1) if (expired()) return;

		unschedule();

		if ((c= getchar()) == ESC) { interrupt(); return; }

		for (e= env; e != nil; e= e->next) {
			switch (menufun(e)) {
			case DEFFUN:
				if (!def) break;
			case USERFUN:
			case SELECT:
				if (c == e->arg[0]) choice= e->value;
			}
		}
	} while (choice == nil);

	/* Execute the chosen function. */
	printf("%c\n", c);
	(void) tokenize(&cmds, choice, &fundef);
}

void help(void)
/* Not everyone is a rocket scientist. */
{
	struct help {
		char	*thing;
		char	*help;
	} *pi;
	static struct help info[] = {
		{ nil,	"Names:" },
		{ "rootdev",		"Root device" },
		{ "ramimagedev",	"RAM disk image if root is RAM" },
		{ "ramsize",		"RAM disk size if root is not RAM" },
		{ "bootdev",		"Special name for the boot device" },
		{ "fd0, hd3, hd2a",	"Devices (as in /dev)" },
		{ "image",		"Name of the kernel image" },
		{ "main",		"Startup function" },
		{ nil,	"Commands:" },
		{ "name = [device] value",  "Set environment variable" },
		{ "name() { ... }",	    "Define function" },
		{ "name(key,text) { ... }",
			"A menu function like: minix(=,Start Minix) {boot}" },
		{ "name",		"Call function" },
		{ "boot [device]",	"Boot Minix or another O.S." },
		{ "delay [msec]",	"Delay (500 msec default)" },
		{ "echo word ...",	"Print the words" },
		{ "ls [directory]",	"List contents of directory" },
		{ "menu",		"Choose a menu function" },
		{ "save",		"Save environment" },
		{ "set",		"Show environment" },
		{ "trap msec command",	"Schedule command" },
		{ "unset name ...",	"Unset variable or set to default" },
		{ "exit",		"Exit the Monitor" },
	};

	for (pi= info; pi < arraylimit(info); pi++) {
		if (pi->thing != nil) printf("    %-24s- ", pi->thing);
		printf("%s\n", pi->help);
	}
}

void execute(void)
/* Get one command from the command chain and execute it. */
{
	token *second, *third, *fourth, *fifth, *sep;
	char *name= cmds->token;
	size_t n= 0;

	/* There must be a separator lurking somewhere. */
	for (sep= cmds; sep != nil && sep->token[0] != ';'; sep= sep->next) n++;

	if ((second= cmds->next) != nil
		&& (third= second->next) != nil
		&& (fourth= third->next) != nil)
			fifth= fourth->next;

		/* Null command? */
	if (n == 0) {
		voidtoken();
		return;
	} else
		/* name = [device] value? */
	if ((n == 3 || n == 4)
		&& !sugar(name)
		&& second->token[0] == '='
		&& !sugar(third->token)
		&& (n == 3 || (n == 4 && third->token[0] == 'd'
					&& !sugar(fourth->token)
	))) {
		char *value= third->token;
		int flags= E_VAR;

		if (n == 4) { value= fourth->token; flags|= E_DEV; }

		if ((flags= b_setvar(flags, name, value)) != 0) {
			printf("%s is a %s\n", name,
				flags & E_RESERVED ? "reserved word" :
						"special function");
			err= 1;
		}
		while (cmds != sep) voidtoken();
		return;
	} else
		/* name '(' arg ')' '{' ... '}'? */
	if (n >= 5
		&& !sugar(name)
		&& second->token[0] == '('
		&& fourth->token[0] == ')'
		&& fifth->token[0] == '{'
	) {
		token *fun= fifth->next;
		int ok= 1, flags;
		char *body;
		size_t len= 1;

		sep= fun;
		while (sep != nil && sep->token[0] != '}') {
			len+= strlen(sep->token) + 1;
			sep= sep->next;
		}
		if (sep == nil || (sep= sep->next) == nil
			|| sep->token[0] != ';'
		) ok= 0;

		if (ok) {
			body= malloc(len * sizeof(char));
			*body= 0;

			while (fun->token[0] != '}') {
				strcat(body, fun->token);
				if (!sugar(fun->token)
					&& !sugar(fun->next->token)
				) strcat(body, " ");
				fun= fun->next;
			}

			if ((flags= b_setenv(E_FUNCTION, name,
						third->token, body)) != 0) {
				printf("%s is a %s\n", name,
					flags & E_RESERVED ? "reserved word" :
							"special variable");
				err= 1;
			}
			while (cmds != sep) voidtoken();
			free(body);
			return;
		}
	} else
		/* Command coming up, check if ESC typed. */
	if (peekchar() == ESC) {
		interrupt();
		return;
	} else
		/* unset name ..., echo word ...? */
	if (n >= 1 && (
		strcmp(name, "unset") == 0
		|| strcmp(name, "echo") == 0
	)) {
		int cmd= name[0];
		char *arg= poptoken();

		for (;;) {
			free(arg);
			if (cmds == sep) break;
			arg= poptoken();
			if (cmd == 'u') {
				b_unset(arg);
			} else {
				printf("%s", arg);
				if (cmds != sep) putchar(' ');
			}
		}
		if (cmd == 'e') putchar('\n');
		return;
	} else
		/* boot -opts? */
	if (n == 2 && strcmp(name, "boot") == 0 && second->token[0] == '-') {
		static char optsvar[]= "bootopts";
		(void) b_setvar(E_VAR, optsvar, second->token);
		bootminix();
		b_unset(optsvar);
		voidtoken();
		voidtoken();
		return;
	} else
		/* boot device, ls dir, delay msec? */
	if (n == 2 && (
		strcmp(name, "boot") == 0
		|| strcmp(name, "delay") == 0
		|| strcmp(name, "ls") == 0
	)) {
		if (name[0] == 'b') boot_device(second->token);
		if (name[0] == 'd') (void) delay(second->token);
		if (name[0] == 'l') ls(second->token);
		voidtoken();
		voidtoken();
		return;
	} else
		/* trap msec command? */
	if (n == 3 && strcmp(name, "trap") == 0 && numeric(second->token)) {
		long msec= a2l(second->token);

		voidtoken();
		voidtoken();
		schedule(msec, poptoken());
		return;
	} else
		/* Simple command. */
	if (n == 1) {
		char *cmd= poptoken();
		char *body;
		int fundef= 0;
		int ok= 0;

		if (strcmp(cmd, "boot") == 0) { bootminix(); ok= 1; }
		if (strcmp(cmd, "delay") == 0) { (void) delay("500"); ok= 1; }
		if (strcmp(cmd, "ls") == 0) { ls(null); ok= 1; }
		if (strcmp(cmd, "menu") == 0) { menu(); ok= 1; }
		if (strcmp(cmd, "save") == 0) { save_parameters(); ok= 1; }
		if (strcmp(cmd, "set") == 0) { show_env(); ok= 1; }
		if (strcmp(cmd, "help") == 0) { help(); ok= 1; }
		if (strcmp(cmd, "exit") == 0) { exit(0); }

		/* Command to check bootparams: */
		if (strcmp(cmd, ":") == 0) ok= 1;

		/* User defined function. */
		if (!ok && (body= b_body(cmd)) != nil) {
			(void) tokenize(&cmds, body, &fundef);
			ok= 1;
		}
		if (!ok) printf("%s: unknown function", cmd);
		free(cmd);
		if (ok) return;
	} else {
		/* Syntax error. */
		printf("Can't parse:");
		while (cmds != sep) {
			printf(" %s", cmds->token); voidtoken();
		}
	}

	/* Getting here means that the command is not understood. */
	printf("\nTry 'help'\n");
	err= 1;
}

void monitor(void)
/* Read one or more lines and tokenize them. */
{
	char *line;
	int fundef= 0;
	token **acmds= &cmds;

	unschedule();	/* Kill a trap. */

	do {
		printf("%s%c", bootdev.name, fundef == 0 ? '>' : '+');
		line= readline();
		acmds= tokenize(acmds, line, &fundef);
		free(line);
	} while (fundef != 0);
}

void boot(void)
/* Load Minix and start it, among other things. */
{
	/* Print greeting message.  The copyright message is not yet displayed,
	 * because this boot program need not necessarily start Minix.
	 */
	reset_video(get_video() & 1 ? COLOR_MODE : MONO_MODE);

	printf("\nMinix boot monitor %s\n", version);
	printf("\nPress ESC to enter the monitor\n");

	/* Initialize tables under DOS. */
	if (DOS) initialize();

	/* Relocate program to the end of memory. */
	migrate();

	/* Initialize tables under the BIOS. */
	if (!DOS) initialize();

	/* Block cache. */
	init_cache();

	/* Get environment variables from the parameter sector. */
	get_parameters();

	/* Read and check the superblock. */
	fsok= r_super() != 0;

	while (1) {
		/* While there are commands, execute them! */
		while (cmds != nil) {
			execute();
			if (err) {
				/* An error, stop interpreting. */
				while (cmds != nil) voidtoken();
				err= 0;
				break;
			}
			(void) expired();
			remote_code();
		}
		/* The "monitor" is just a "read one command" thing. */
		monitor();
	}
}

⌨️ 快捷键说明

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