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

📄 boot.c

📁 操作系统引导监控程序
💻 C
📖 第 1 页 / 共 3 页
字号:
#else /* DOS */
	/* Initialize under DOS: Open virtual disk to boot Minix from, grab
	 * extended memory, etc.
	 */
	char *argp, *vdisk;

	/* Parse the command line. */
	argp= PSP + 0x81;
	argp[PSP[0x80]]= 0;
	while (between('\1', *argp, ' ')) argp++;
	vdisk= argp;
	while (!between('\0', *argp, ' ')) argp++;
	while (between('\1', *argp, ' ')) *argp++= 0;
	if (*argp != 0 || *vdisk == 0) {
		printf("\nUsage: boot <vdisk>\n");
		exit(1);
	}

	if ((r= dos_open(vdisk)) != 0) {
		printf("\n%s: Error %02x (%s)\n", vdisk, r, bios_err(r));
		exit(1);
	}

	/* Find the active partition on the virtual disk. */
	if ((r= get_master(master, table, 0)) != 0) {
		readerr(0, r); exit(1);
	}

	strcpy(bootdev.name, "dosd0");
	bootdev.primary= -1;
	for (p= 0; p < NR_PARTITIONS; p++) {
		if (table[p]->bootind != 0 && table[p]->sysind == MINIX_PART) {
			bootdev.primary= p;
			bootdev.name[4]= '1' + p;
			lowsec= table[p]->lowsec;
			break;
		}
	}
#endif /* DOS */
}

char null[]= "";	/* This kludge saves lots of memory. */

void sfree(char *s)
/* Free a non-null string. */
{
	if (s != nil && s != null) free(s);
}

char *copystr(char *s)
/* Copy a non-null string using malloc. */
{
	char *c;

	if (*s == 0) return null;
	c= malloc((strlen(s) + 1) * sizeof(char));
	strcpy(c, s);
	return c;
}

int is_default(environment *e)
{
	return (e->flags & E_SPECIAL) && e->defval == nil;
}

environment **searchenv(char *name)
{
	environment **aenv= &env;

	while (*aenv != nil && strcmp((*aenv)->name, name) != 0) {
		aenv= &(*aenv)->next;
	}

	return aenv;
}

#define b_getenv(name)	(*searchenv(name))
/* Return the environment *structure* belonging to name, or nil if not found. */

char *b_value(char *name)
/* The value of a variable. */
{
	environment *e= b_getenv(name);

	return e == nil || !(e->flags & E_VAR) ? nil : e->value;
}

char *b_body(char *name)
/* The value of a function. */
{
	environment *e= b_getenv(name);

	return e == nil || !(e->flags & E_FUNCTION) ? nil : e->value;
}

int b_setenv(int flags, char *name, char *arg, char *value)
/* Change the value of an environment variable.  Returns the flags of the
 * variable if you are not allowed to change it, 0 otherwise.
 */
{
	environment **aenv, *e;

	if (*(aenv= searchenv(name)) == nil) {
		e= malloc(sizeof(*e));
		e->name= copystr(name);
		e->flags= flags;
		e->defval= nil;
		e->next= nil;
		*aenv= e;
	} else {
		e= *aenv;

		/* Don't touch reserved names and don't change special
		 * variables to functions or vv.
		 */
		if (e->flags & E_RESERVED || (e->flags & E_SPECIAL
			&& (e->flags & E_FUNCTION) != (flags & E_FUNCTION)
		)) return e->flags;

		e->flags= (e->flags & E_STICKY) | flags;
		if (is_default(e)) {
			e->defval= e->value;
		} else {
			sfree(e->value);
		}
		sfree(e->arg);
	}
	e->arg= copystr(arg);
	e->value= copystr(value);
	return 0;
}

int b_setvar(int flags, char *name, char *value)
/* Set variable or simple function. */
{
	return b_setenv(flags, name, null, value);
}

void b_unset(char *name)
/* Remove a variable from the environment.  A special variable is reset to
 * its default value.
 */
{
	environment **aenv, *e;

	if ((e= *(aenv= searchenv(name))) == nil) return;

	if (e->flags & E_SPECIAL) {
		if (e->defval != nil) {
			sfree(e->arg);
			e->arg= null;
			sfree(e->value);
			e->value= e->defval;
			e->defval= nil;
		}
	} else {
		sfree(e->name);
		sfree(e->arg);
		sfree(e->value);
		*aenv= e->next;
		free(e);
	}
}

long a2l(char *a)
/* Cheap atol(). */
{
	int sign= 1;
	long n= 0;

	if (*a == '-') { sign= -1; a++; }

	while (between('0', *a, '9')) n= n * 10 + (*a++ - '0');

	return sign * n;
}

char *ul2a(u32_t n)
/* Transform a long number to ascii digits. */
{
	static char num[3 * sizeof(n)];
	char *a= arraylimit(num) - 1;

	do *--a = (n % 10) + '0'; while ((n/= 10) > 0);
	return a;
}

char *u2a(U16_t n)
/* Transform a short number to ascii digits. */
{
	return ul2a(n);
}

unsigned a2x(char *a)
/* Ascii to hex. */
{
	unsigned n= 0;
	int c;

	for (;;) {
		c= *a;
		if (between('0', c, '9')) c= c - '0' + 0x0;
		else
		if (between('A', c, 'F')) c= c - 'A' + 0xA;
		else
		if (between('a', c, 'f')) c= c - 'a' + 0xa;
		else
			break;
		n= (n<<4) | c;
		a++;
	}
	return n;
}

void get_parameters(void)
{
	char params[SECTOR_SIZE + 1];
	token **acmds;
	int r, fundef= 0;
	static char bus_type[][4] = {
		"xt", "at", "mca"
	};
	static char vid_type[][4] = {
		"mda", "cga", "ega", "ega", "vga", "vga"
	};
	static char vid_chrome[][6] = {
		"mono", "color"
	};

	/* Variables that Minix needs: */
	b_setvar(E_SPECIAL|E_VAR|E_DEV, "rootdev", "ram");
	b_setvar(E_SPECIAL|E_VAR|E_DEV, "ramimagedev", "bootdev");
	b_setvar(E_SPECIAL|E_VAR, "ramsize", "0");
	b_setvar(E_SPECIAL|E_VAR, "processor", u2a(getprocessor()));
	b_setvar(E_SPECIAL|E_VAR, "bus", bus_type[get_bus()]);
	b_setvar(E_SPECIAL|E_VAR, "memsize", u2a(get_memsize()));
	b_setvar(E_SPECIAL|E_VAR, "emssize", ul2a(get_ext_memsize()));
	b_setvar(E_SPECIAL|E_VAR, "video", vid_type[get_video()]);
	b_setvar(E_SPECIAL|E_VAR, "chrome", vid_chrome[get_video() & 1]);

	/* Variables boot needs: */
	b_setvar(E_SPECIAL|E_VAR, "image", "minix");
	b_setvar(E_SPECIAL|E_FUNCTION, "main", "menu");

	/* Default menu function: */
	b_setenv(E_RESERVED|E_FUNCTION, "\1", "=,Start Minix", "boot");

	/* Reserved names: */
	b_setvar(E_RESERVED, "boot", null);
	b_setvar(E_RESERVED, "menu", null);
	b_setvar(E_RESERVED, "set", null);
	b_setvar(E_RESERVED, "unset", null);
	b_setvar(E_RESERVED, "save", null);
	b_setvar(E_RESERVED, "ls", null);
	b_setvar(E_RESERVED, "echo", null);
	b_setvar(E_RESERVED, "trap", null);
	b_setvar(E_RESERVED, "help", null);
	b_setvar(E_RESERVED, "exit", null);

	/* Tokenize bootparams sector. */
	if ((r= readsectors(mon2abs(params), lowsec+PARAMSEC, 1)) != 0) {
		readerr(lowsec+PARAMSEC, r);
		exit(1);
	}
	params[SECTOR_SIZE]= 0;
	acmds= tokenize(&cmds, params, &fundef);

	/* Stuff the default action into the command chain. */
	(void) tokenize(acmds, ":;main", &fundef);
}

void remote_code(void)
/* A rebooting Minix returns a bit of code for the monitor. */
{
	if (reboot_code != 0) {
		char code[SECTOR_SIZE + 2];
		int fundef= 0;

		raw_copy(mon2abs(code), reboot_code, SECTOR_SIZE);
		code[SECTOR_SIZE]= 0;
		strcat(code, ";");
		(void) tokenize(&cmds, code, &fundef);
		reboot_code= 0;
	}
}

char *addptr;

void addparm(char *n)
{
	while (*n != 0 && *addptr != 0) *addptr++ = *n++;
}

void save_parameters(void)
/* Save nondefault environment variables to the bootparams sector. */
{
	environment *e;
	char params[SECTOR_SIZE + 1];
	int r;

	/* Default filling: */
	memset(params, '\n', SECTOR_SIZE);

	/* Don't touch the 0! */
	params[SECTOR_SIZE]= 0;
	addptr= params;

	for (e= env; e != nil; e= e->next) {
		if (e->flags & E_RESERVED || is_default(e)) continue;

		addparm(e->name);
		if (e->flags & E_FUNCTION) {
			addparm("(");
			addparm(e->arg);
			addparm("){");
		} else {
			addparm((e->flags & (E_DEV|E_SPECIAL)) != E_DEV
							? "=" : "=d ");
		}
		addparm(e->value);
		if (e->flags & E_FUNCTION) addparm("}");
		if (*addptr == 0) {
			printf("The environment is too big\n");
			return;
		}
		*addptr++= '\n';
	}

	/* Save the parameters on disk. */
	if ((r= writesectors(mon2abs(params), lowsec+PARAMSEC, 1)) != 0) {
		writerr(lowsec+PARAMSEC, r);
		printf("Can't save environment\n");
	}
}

void show_env(void)
/* Show the environment settings. */
{
	environment *e;

	for (e= env; e != nil; e= e->next) {
		if (e->flags & E_RESERVED) continue;

		if (e->flags & E_FUNCTION) {
			printf("%s(%s) {%s}\n", e->name, e->arg, e->value);
		} else {
			printf(is_default(e) ? "%s = (%s)\n" : "%s = %s\n",
				e->name, e->value);
		}
	}
}

int numprefix(char *s, char **ps)
/* True iff s is a string of digits.  *ps will be set to the first nondigit
 * if non-nil, otherwise the string should end.
 */
{
	char *n= s;

	while (between('0', *n, '9')) n++;

	if (n == s) return 0;

	if (ps == nil) return *n == 0;

	*ps= n;
	return 1;
}

int numeric(char *s)
{
	return numprefix(s, (char **) nil);
}

/* Device numbers of standard Minix devices. */
#define DEV_RAM		0x0100
#define DEV_FD0		0x0200
#define DEV_HD0		0x0300
#define DEV_SD0  	0x0A00
#define minor_1a	   128

dev_t name2dev(char *name)
/* Translate, say, /dev/hd3 to a device number.  If the name can't be
 * found on the boot device, then do some guesswork.  The global structure
 * "tmpdev" will be filled in based on the name, so that "boot hd6" knows
 * what device to boot without interpreting device numbers.
 */
{
	dev_t dev;
	ino_t ino;
	int drive;
	struct stat st;
	char *n, *s;

	/* "boot *hd3" means: make partition 3 active before you boot it. */
	if ((activate= (name[0] == '*'))) name++;

	/* The special name "bootdev" must be translated to the boot device. */
	if (strcmp(name, "bootdev") == 0) {
		if (bootdev.device == -1) {
			printf("The boot device could not be named\n");
			errno= 0;
			return -1;
		}
		name= bootdev.name;
	}

	/* If our boot device doesn't have a file system, or we want to know
	 * what a name means for the BIOS, then we need to interpret the
	 * device name ourselves: "fd" = floppy, "hd" = hard disk, etc.
	 */
	tmpdev.device= tmpdev.primary= tmpdev.secondary= -1;
	dev= -1;
	n= name;
	if (strncmp(n, "/dev/", 5) == 0) n+= 5;

	if (strcmp(n, "ram") == 0) {
		dev= DEV_RAM;
	} else
	if (n[0] == 'f' && n[1] == 'd' && numeric(n+2)) {
		/* Floppy. */
		tmpdev.device= a2l(n+2);
		dev= DEV_FD0 + tmpdev.device;
	} else
	if ((n[0] == 'h' || n[0] == 's') && n[1] == 'd' && numprefix(n+2, &s)
		&& (*s == 0 || (between('a', *s, 'd') && s[1] == 0))
	) {
		/* Hard disk. */
		dev= a2l(n+2);
		tmpdev.device= dev / (1 + NR_PARTITIONS);
		tmpdev.primary= (dev % (1 + NR_PARTITIONS)) - 1;
		if (*s != 0) {
			/* Subpartition. */
			tmpdev.secondary= *s - 'a';
			dev= minor_1a
				+ (tmpdev.device * NR_PARTITIONS
					+ tmpdev.primary) * NR_PARTITIONS
				+ tmpdev.secondary;
		}
		tmpdev.device+= 0x80;
		dev+= n[0] == 'h' ? DEV_HD0 : DEV_SD0;
	}

	/* Look the name up on the boot device for the UNIX device number. */
	if (fsok) {
		/* The current working directory is "/dev". */
		ino= r_lookup(r_lookup(ROOT_INO, "dev"), name);

		if (ino != 0) {
			/* Name has been found, extract the device number. */
			r_stat(ino, &st);
			if (!S_ISBLK(st.st_mode)) {
				printf("%s is not a block device\n", name);
				errno= 0;
				return (dev_t) -1;
			}
			dev= st.st_rdev;
		}
	}

	if (tmpdev.primary < 0) activate= 0;	/* Careful now! */

	if (dev == -1) {
		printf("Can't recognize '%s' as a device\n", name);
		errno= 0;
	}
	return dev;
}

#if !DOS
#define B_NODEV		-1
#define B_NOSIG		-2

int exec_bootstrap(dev_t dev)
/* Load boot sector from the disk or floppy described by tmpdev and execute it.
 * The floppy parameters may not be right for the floppy we want to read, but
 * reading sector 0 seems to be no problem.
 */
{
	int r, n, dirty= 0;
	char master[SECTOR_SIZE];
	struct part_entry *table[NR_PARTITIONS], dummy, *active= &dummy;
	u32_t masterpos;

	device= tmpdev.device;
	if (!dev_geometry()) return B_NODEV;

	active->lowsec= 0;

	/* Select a partition table entry. */
	while (tmpdev.primary >= 0) {
		masterpos= active->lowsec;

		if ((r= get_master(master, table, masterpos)) != 0) return r;

		active= table[tmpdev.primary];

		/* How does one check a partition table entry? */
		if (active->sysind == NO_PART) return B_NOSIG;

		tmpdev.primary= tmpdev.secondary;
		tmpdev.secondary= -1;
	}

	if (activate && !active->bootind) {
		for (n= 0; n < NR_PARTITIONS; n++) table[n]->bootind= 0;

⌨️ 快捷键说明

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