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

📄 bootimage.c

📁 操作系统加载的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			return;
		}
		procp= &process[i];

		/* Read header. */
		for (;;) {
			if ((buf= get_sector(vsec++)) == nil) return;

			memcpy(&hdr, buf, sizeof(hdr));

			if (BADMAG(hdr.process)) { errno= ENOEXEC; return; }

			/* Check the optional label on the process. */
			if (selected(hdr.name)) break;

			/* Bad label, skip this process. */
			vsec+= proc_size(&hdr);
		}

		/* Place a copy of the header where the kernel can get it. */
		raw_copy(HEADERPOS + i * A_MINHDR, mon2abs(&hdr.process),
								A_MINHDR);

		/* Sanity check: an 8086 can't run a 386 kernel. */
		if (hdr.process.a_cpu == A_I80386 && processor < 386) {
			printf("You can't run a 386 kernel on this 80%ld\n",
				processor);
			errno= 0;
			return;
		}

		/* Get the click shift from the kernel text segment. */
		if (i == KERNEL) {
			if (!get_clickshift(vsec, &hdr)) return;
			addr= align(addr, click_size);
		}

		if (!banner) {
			printf("    cs      ds    text    data     bss");
			if (k_flags & K_CHMEM) printf("   stack");
			putchar('\n');
			banner= 1;
		}

		/* Segment sizes. */
		a_text= hdr.process.a_text;
		a_data= hdr.process.a_data;
		a_bss= hdr.process.a_bss;
		if (k_flags & K_CHMEM) {
			a_stack= hdr.process.a_total - a_data - a_bss;
			if (!(hdr.process.a_flags & A_SEP)) a_stack-= a_text;
		} else {
			a_stack= 0;
		}

		/* Collect info about the process to be. */
		strcpy(procp->name, hdr.name);
		procp->cs= addr;

		/* Process may be page aligned so that the text segment contains
		 * the header, or have an unmapped zero page against vaxisms.
		 */
		procp->entry= hdr.process.a_entry;
		if (hdr.process.a_flags & A_PAL) a_text+= hdr.process.a_hdrlen;
		if (hdr.process.a_flags & A_UZP) procp->cs-= click_size;

		/* Separate I&D: two segments.  Common I&D: only one. */
		if (hdr.process.a_flags & A_SEP) {
			/* Read the text segment. */
			if (!get_segment(&vsec, &a_text, &addr, limit)) return;

			/* The data segment follows. */
			procp->ds= addr;
			if (hdr.process.a_flags & A_UZP) procp->ds-= click_size;
			procp->data= addr;
		} else {
			/* Add text to data to form one segment. */
			procp->data= addr + a_text;
			procp->ds= procp->cs;
			a_data+= a_text;
		}

		printf("%06lx  %06lx%8ld%8ld%8ld",
			procp->cs, procp->ds,
			hdr.process.a_text, hdr.process.a_data,
			hdr.process.a_bss
		);
		if (k_flags & K_CHMEM) printf("%8ld", a_stack);

		printf("  %s\n", hdr.name);

		/* Read the data segment. */
		if (!get_segment(&vsec, &a_data, &addr, limit)) return;

		/* Make space for bss and stack unless... */
		if (i != KERNEL && (k_flags & K_CLAIM)) a_bss= a_stack= 0;

		/* Note that a_data may be negative now, but we can look at it
		 * as -a_data bss bytes.
		 */

		/* Compute the number of bss clicks left. */
		a_bss+= a_data;
		n= align(a_bss, click_size);
		a_bss-= n;

		/* Zero out bss. */
		if (addr + n > limit) { errno= ENOMEM; return; }
		raw_clear(addr, n);
		addr+= n;

		/* And the number of stack clicks. */
		a_stack+= a_bss;
		n= align(a_stack, click_size);
		a_stack-= n;

		/* Add space for the stack. */
		addr+= n;

		/* Process endpoint. */
		procp->end= addr;

		if (i == 0 && (k_flags & K_HIGH)) {
			/* Load the rest in extended memory. */
			addr= 0x100000L;
			limit= 0x100000L + get_ext_memsize() * 1024L;
		}
	}

	if ((n_procs= i) == 0) {
		printf("There are no programs in %s\n", image);
		errno= 0;
		return;
	}

	/* Check the kernel magic number. */
	if (get_word(process[KERNEL].data + MAGIC_OFF) != KERNEL_D_MAGIC) {
		printf("%s magic number is incorrect\n", process[KERNEL].name);
		errno= 0;
		return;
	}

	/* Patch sizes, etc. into kernel data. */
	patch_sizes();

	/* Wait a while if delay is set, bail out if ESC typed. */
	msec= b_value("delay");
	if (!delay(msec != nil ? msec : "0")) { errno= 0; return; }

	/* Reset the screen setting the proper video mode.  This is more
	 * important than it seems, Minix depends on the mode set right.
	 */
	mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE : MONO_MODE;
	console= b_value("console");
	if (console != nil && a2x(console) != 0) mode= a2x(console);
	reset_video(mode);

	/* Minix. */
	reboot_code= minix(process[KERNEL].entry, process[KERNEL].cs,
				process[KERNEL].ds, params, paramsize);

	/* Boot file system still around? */
	fsok= r_super() != 0;
	errno= 0;
}

char *params2params(size_t *size)
/* Repackage the environment settings for the kernel. */
{
	char *parms;
	size_t i, z;
	environment *e;

	i= 0;
	z= 64;
	parms= malloc(z * sizeof(char *));

	for (e= env; e != nil; e= e->next) {
		char *name= e->name, *value= e->value;
		size_t n;
		dev_t dev;

		if (!(e->flags & E_VAR)) continue;

		if (e->flags & E_DEV) {
			if ((dev= name2dev(value)) == -1) {
				free(parms);
				errno= 0;
				return nil;
			}
			value= u2a((u16_t) dev);
		}

		n= i + strlen(name) + 1 + strlen(value) + 1;
		if (n > z) {
			z+= n;
			parms= realloc(parms, z * sizeof(char));
		}
		strcpy(parms + i, name);
		strcat(parms + i, "=");
		strcat(parms + i, value);
		i= n;
	}
	parms[i++]= 0;	/* End marked with empty string. */
	*size= i;
	return parms;
}

ino_t latest_version(char *version, struct stat *stp)
/* Recursively read the current directory, selecting the newest image on
 * the way up.  (One can't use r_stat while reading a directory.)
 */
{
	char name[NAME_MAX + 1];
	ino_t ino, newest;
	time_t mtime;

	if ((ino= r_readdir(name)) == 0) { stp->st_mtime= 0; return 0; }

	newest= latest_version(version, stp);
	mtime= stp->st_mtime;
	r_stat(ino, stp);

	if (S_ISREG(stp->st_mode) && stp->st_mtime > mtime) {
		newest= ino;
		strcpy(version, name);
	} else {
		stp->st_mtime= mtime;
	}
	return newest;
}

char *select_image(char *image)
/* Look image up on the filesystem, if it is a file then we're done, but
 * if its a directory then we want the newest file in that directory.  If
 * it doesn't exist at all, then see if it is 'number:number' and get the
 * image from that absolute offset off the disk.
 */
{
	ino_t image_ino;
	struct stat st;

	image= strcpy(malloc((strlen(image) + 1 + NAME_MAX + 1)
						 * sizeof(char)), image);

	if (!fsok || (image_ino= r_lookup(ROOT_INO, image)) == 0) {
		char *size;

		if (numprefix(image, &size) && *size++ == ':'
						&& numeric(size)) {
			vir2sec= flat_vir2sec;
			image_off= a2l(image);
			image_size= a2l(size);
			strcpy(image, "Minix");
			return image;
		}
		if (!fsok)
			printf("No image selected\n");
		else
			printf("Can't load %s: %s\n", image, unix_err(errno));
		goto bail_out;
	}

	r_stat(image_ino, &st);
	if (!S_ISREG(st.st_mode)) {
		char *version= image + strlen(image);
		char dots[NAME_MAX + 1];

		if (!S_ISDIR(st.st_mode)) {
			printf("%s: %s\n", image, unix_err(ENOTDIR));
			goto bail_out;
		}
		(void) r_readdir(dots);
		(void) r_readdir(dots);	/* "." & ".." */
		*version++= '/';
		*version= 0;
		if ((image_ino= latest_version(version, &st)) == 0) {
			printf("There are no images in %s/\n", image);
			goto bail_out;
		}
		r_stat(image_ino, &st);
	}
	vir2sec= file_vir2sec;
	image_size= (st.st_size + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
	return image;
bail_out:
	free(image);
	return nil;
}

void bootminix(void)
/* Load Minix and run it.  (Given the size of this program it is surprising
 * that it ever gets to that.)
 */
{
	char *image;
	char *minixparams;
	size_t paramsize;

	/* Translate the bootparameters to what Minix likes best. */
	if ((minixparams= params2params(&paramsize)) == nil) return;

	if ((image= select_image(b_value("image"))) == nil) return;

	/* Things are getting serious, kill the cache! */
	invalidate_cache();

	printf("\nLoading ");
	pretty_image(image);
	printf(".\n\n");

	exec_image(image, minixparams, paramsize);

	switch (errno) {
	case ENOEXEC:
		printf("%s contains a bad program header\n", image);
		break;
	case ENOMEM:
		printf("Not enough memory to load %s\n", image);
		break;
	case EIO:
		printf("Unsuspected EOF on %s\n", image);
	case 0:
		/* No error or error already reported. */;
	}
	/* Put all that free memory to use again. */
	init_cache();

	free(minixparams);
	free(image);
}

⌨️ 快捷键说明

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