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

📄 installboot.c

📁 操作系统磁盘分区的源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
	*len= sec - *start;
	printf("%8ld%8ld  %s\n", *start, *len, file);
	*start= sec;
	return 1;
}

enum howto { FS, BOOT };

void make_bootable(enum howto how, char *device, char *bootblock,
					char *bootcode, char **imagev)
/* Install bootblock on the bootsector of device with the disk addresses to
 * bootcode patched into the data segment of bootblock.  "How" tells if there
 * should or shoudn't be a file system on the disk.  The images in the imagev
 * vector are added to the end of the device.
 */
{
	char buf[BLOCK_SIZE + 256], *adrp, *parmp;
	struct fileaddr {
		off_t	address;
		int	count;
	} bootaddr[BOOT_MAX + 1], *bap= bootaddr;
	struct exec boothdr;
	struct image_header dummy;
	struct stat st;
	ino_t ino;
	off_t sector, max_sector;
	FILE *bootf;
	off_t addr, fssize, pos, len;
	char *labels, *label, *image;
	int nolabel;

	/* Open device and set variables for readblock. */
	if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);

	/* Read and check the superblock. */
	fssize= r_super();

	switch (how) {
	case FS:
		if (fssize == 0) {
			fprintf(stderr,
				"installboot: %s is not a Minix file system\n",
				device);
			exit(1);
		}
		break;
	case BOOT:
		if (fssize != 0) {
			int s;
			printf("%s contains a file system!\n", device);
			printf("Scribbling in 10 seconds");
			for (s= 0; s < 10; s++) {
				fputc('.', stdout);
				fflush(stdout);
				sleep(1);
			}
			fputc('\n', stdout);
		}
		fssize= 1;	/* Just a boot block. */
	}

	if (how == FS) {
		/* See if the boot code can be found on the file system. */
		if ((ino= r_lookup(ROOT_INO, bootcode)) == 0) {
			if (errno != ENOENT) fatal(bootcode);
		}
	} else {
		/* Boot code must be attached at the end. */
		ino= 0;
	}

	if (ino == 0) {
		/* For a raw installation, we need to copy the boot code onto
		 * the device, so we need to look at the file to be copied.
		 */
		if (stat(bootcode, &st) < 0) fatal(bootcode);

		if ((bootf= fopen(bootcode, "r")) == nil) fatal(bootcode);
	} else {
		/* Boot code is present in the file system. */
		r_stat(ino, &st);

		/* Get the header from the first block. */
		if ((addr= r_vir2abs((off_t) 0)) == 0) {
			boothdr.a_magic[0]= !A_MAGIC0;
		} else {
			readblock(addr, buf);
			memcpy(&boothdr, buf, sizeof(struct exec));
		}
		bootf= nil;
		dummy.process= boothdr;
	}
	/* See if it is an executable (read_header does the check). */
	read_header(0, bootcode, bootf, &dummy);
	boothdr= dummy.process;

	if (bootf != nil) fclose(bootf);

	/* Get all the sector addresses of the secondary boot code. */
	max_sector= (boothdr.a_hdrlen + boothdr.a_text
			+ boothdr.a_data + SECTOR_SIZE - 1) / SECTOR_SIZE;

	if (max_sector > BOOT_MAX * RATIO) {
		fprintf(stderr, "installboot: %s is way too big\n", bootcode);
		exit(0);
	}

	/* Determine the addresses to the boot code to be patched into the
	 * boot block.
	 */
	bap->count= 0;	/* Trick to get the address recording going. */

	for (sector= 0; sector < max_sector; sector++) {
		if (ino == 0) {
			addr= fssize + (sector / RATIO);
		} else
		if ((addr= r_vir2abs(sector / RATIO)) == 0) {
			fprintf(stderr, "installboot: %s has holes!\n",
								bootcode);
			exit(1);
		}
		addr= (addr * RATIO) + (sector % RATIO);

		/* First address of the addresses array? */
		if (bap->count == 0) bap->address= addr;

		/* Paste sectors together in a multisector read. */
		if (bap->address + bap->count == addr)
			bap->count++;
		else {
			/* New address. */
			bap++;
			bap->address= addr;
			bap->count= 1;
		}
	}
	(++bap)->count= 0;	/* No more. */

	/* Get the boot block and patch the pieces in. */
	readblock(BOOTBLOCK, buf);

	if ((bootf= fopen(bootblock, "r")) == nil) fatal(bootblock);

	read_header(0, bootblock, bootf, &dummy);
	boothdr= dummy.process;

	if (boothdr.a_text + boothdr.a_data +
					 4 * (bap - bootaddr) + 1 > SIGPOS) {
		fprintf(stderr,
	"installboot: %s + addresses to %s don't fit in the boot sector\n",
			bootblock, bootcode);
		fprintf(stderr,
		    "You can try copying/reinstalling %s to defragment it\n",
			bootcode);
		exit(1);
	}

	/* All checks out right.  Read bootblock into the boot block! */
	bread(bootf, bootblock, buf, boothdr.a_text + boothdr.a_data);
	(void) fclose(bootf);

	/* Patch the addresses in. */
	adrp= buf + (int) (boothdr.a_text + boothdr.a_data);
	for (bap= bootaddr; bap->count != 0; bap++) {
		*adrp++= bap->count;
		*adrp++= (bap->address >>  0) & 0xFF;
		*adrp++= (bap->address >>  8) & 0xFF;
		*adrp++= (bap->address >> 16) & 0xFF;
	}
	/* Zero count stops bootblock's reading loop. */
	*adrp++= 0;

	if (bap > bootaddr+1) {
		printf("%s and %d addresses to %s patched into %s\n",
			bootblock, (int)(bap - bootaddr), bootcode, device);
	}

	/* Boot block signature. */
	adrp= buf + SIGPOS;
	*adrp++= (SIGNATURE >> 0) & 0xFF;
	*adrp++= (SIGNATURE >> 8) & 0xFF;

	/* Sector 2 of the boot block is used for boot parameters, initially
	 * filled with null commands (newlines).  Initialize it only if
	 * necessary.
	 */
	for (parmp= buf + SECTOR_SIZE; parmp < buf + 2*SECTOR_SIZE; parmp++) {
		if (*imagev != nil || (control(*parmp) && *parmp != '\n')) {
			/* Param sector must be initialized. */
			memset(buf + SECTOR_SIZE, '\n', SECTOR_SIZE);
			break;
		}
	}

	/* Offset to the end of the file system to add boot code and images. */
	pos= fssize * RATIO;

	if (ino == 0) {
		/* Place the boot code onto the boot device. */
		len= max_sector;
		if (!raw_install(bootcode, &pos, &len)) {
			if (how == FS) {
				fprintf(stderr,
	"\t(Isn't there a copy of %s on %s that can be used?)\n",
					bootcode, device);
			}
			exit(1);
		}
	}

	parmp= buf + SECTOR_SIZE;
	nolabel= 0;

	if (how == BOOT) {
		/* A boot only disk needs to have floppies swapped. */
		strcpy(parmp, "delay=swap\n");
		parmp+= strlen(parmp);
	}

	while ((labels= *imagev++) != nil) {
		/* Place each kernel image on the boot device. */

		if ((image= strchr(labels, ':')) != nil)
			*image++= 0;
		else {
			if (nolabel) {
				fprintf(stderr,
			    "installboot: Only one image can be the default\n");
				exit(1);
			}
			nolabel= 1;
			image= labels;
			labels= nil;
		}
		len= 0;
		if (!raw_install(image, &pos, &len)) exit(1);

		if (labels == nil) {
			/* Let this image be the default. */
			sprintf(parmp, "image=%ld:%ld\n", pos-len, len);
			parmp+= strlen(parmp);
		}

		while (labels != nil) {
			/* Image is prefixed by a comma separated list of
			 * labels.  Define functions to select label and image.
			 */
			label= labels;
			if ((labels= strchr(labels, ',')) != nil) *labels++ = 0;

			sprintf(parmp,
		"%s(%c){label=%s;image=%ld:%ld;echo %s kernel selected;menu}\n",
				label,
				between('A', label[0], 'Z')
					? label[0]-'A'+'a' : label[0],
				label, pos-len, len, label);
			parmp+= strlen(parmp);
		}

		if (parmp > buf + BLOCK_SIZE) {
			fprintf(stderr,
		"installboot: Out of parameter space, too many images\n");
			exit(1);
		}
	}
	/* Install boot block. */
	writeblock((off_t) BOOTBLOCK, buf);

	if (pos > fssize * RATIO) {
		/* Tell the total size of the data on the device. */
		printf("%16ld  (%ld kb) total\n", pos,
						(pos + RATIO - 1) / RATIO);
	}
}

void install_master(char *device, char *masterboot, char *fix)
/* Booting a hard disk is a two stage process:  The master bootstrap in sector
 * 0 loads the bootstrap from sector 0 of the active partition which in turn
 * starts the operating system.  This code installs such a master bootstrap
 * on a hard disk.  If fix is non-null then the master bootstrap is locked
 * into booting device /dev/hd'fix'.
 */
{
	FILE *masf;
	unsigned long size;
	struct stat st;
	char buf[BLOCK_SIZE];

	/* Open device. */
	if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);

	/* Open the master boot code. */
	if ((masf= fopen(masterboot, "r")) == nil) fatal(masterboot);

	/* See if the user is cloning a device. */
	if (fstat(fileno(masf), &st) >=0 && S_ISBLK(st.st_mode))
		size= PARTPOS;
	else {
		/* Read and check header otherwise. */
		struct image_header ihdr;

		read_header(1, masterboot, masf, &ihdr);
		size= ihdr.process.a_text + ihdr.process.a_data;
	}
	if (size > PARTPOS) {
		fprintf(stderr, "installboot: %s is too big\n", masterboot);
		exit(1);
	}
	/* Read the master boot block, patch it, write. */
	readblock(BOOTBLOCK, buf);

	(void) bread(masf, masterboot, buf, size);

	if (fix != nil) {
		/* Fixate partition to boot. */
		int device= 0, logical= 0;
		char *pf= fix;

		while (between('0', *pf, '9')) {
			device= 10 * device + (*pf - '0');
			if (device >= 40) break;
			pf++;
		}
		if (between('a', *pf, 'd')) {
			logical= 1 + (*pf - 'a');
			pf++;
		}
		if (*pf != 0) {
			fprintf(stderr, "installboot: bad fix key '%s'\n", fix);
			exit(1);
		}

		if (buf[0] == (char) JMP && buf[1] == (char) JMPOFFM
				&& buf[3] == (char) XOR && logical == 0) {
			/* Minix masterboot; patch device number. */
			buf[2]= device;
		} else
		if (buf[0] == (char) JMP && buf[1] == (char) JMPOFFE
				&& buf[4] == (char) XOR && logical != 0) {
			/* Minix extboot; patch device and logical number. */
			buf[2]= device;
			buf[3]= logical;
		} else {
			fprintf(stderr,
				"installboot: can't put fix flag '%s' on %s\n",
				fix, masterboot);
			exit(1);
		}
	}

	/* Install signature. */
	buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
	buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;

	writeblock(BOOTBLOCK, buf);
}

void usage(void)
{
	fprintf(stderr,
		"Usage: installboot -i(mage) image kernel mm fs ... init\n");
	fprintf(stderr,
		"       installboot -(e)x(tract) image\n");
	fprintf(stderr,
		"       installboot -d(evice) device bootblock boot\n");
	fprintf(stderr,
		"       installboot -b(oot) device bootblock boot image ...\n");
	fprintf(stderr,
		"       installboot -m(aster) [fix] device masterboot\n");
	exit(1);
}

int isoption(char *option, char *test)
/* Check if the option argument is equals "test".  Also accept -i as short
 * for -image, and the special case -x for -extract.
 */
{
	if (strcmp(option, test) == 0) return 1;
	if (option[0] != '-' && strlen(option) != 2) return 0;
	if (option[1] == test[1]) return 1;
	if (option[1] == 'x' && test[1] == 'e') return 1;
	return 0;
}

int main(int argc, char **argv)
{
	if (argc < 2) usage();

	if (argc >= 4 && isoption(argv[1], "-image")) {
		make_image(argv[2], argv + 3);
	} else
	if (argc == 3 && isoption(argv[1], "-extract")) {
		extract_image(argv[2]);
	} else
	if (argc >= 5 && isoption(argv[1], "-device")) {
		make_bootable(FS, argv[2], argv[3], argv[4], argv + 5);
	} else
	if (argc >= 6 && isoption(argv[1], "-boot")) {
		make_bootable(BOOT, argv[2], argv[3], argv[4], argv + 5);
	} else
	if (argc == 4 && isoption(argv[1], "-master")) {
		install_master(argv[2], argv[3], nil);
	} else
	if (argc == 5 && isoption(argv[1], "-master")
				    && between('0', argv[2][0], '9')) {
		install_master(argv[3], argv[4], argv[2]);
	} else {
		usage();
	}
	exit(0);
}

⌨️ 快捷键说明

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