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

📄 installboot.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
#ifndef lintstatic	char sccsid[] = "@(#)installboot.c 1.1 92/07/30 Copyr 1983 Sun Micro";#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * installboot.c * * Install the bootblk program in the boot block. * The real boot program will be read via a table * of entries that point to where the boot program * is stored in the file system. */#include <stdio.h>#include <sys/types.h>#include <sys/exec.h>#include <sys/file.h>#include <sys/param.h>#include <sys/time.h>#include <sys/vnode.h>#include <ufs/fs.h>#include <ufs/inode.h>#include <sys/stat.h>#include <sys/dir.h>#define NDBLKS		64#define SECTORSIZE	512#define SUPERADDR	(16 * SECTORSIZE)#define BOOTBLKSIZE	((16 - 1) * SECTORSIZE)#define MAXBSIZE	8192		/* maximum fs block size supported */long	superblock[SBSIZE / sizeof (long)];long	ibuf[MAXBSIZE / sizeof (long)];char	vflg = 0;char	lflg = 0;#if defined(sun4c) || defined (sun4m)char	hflg = 1;#elsechar	hflg = 0;#endif/* * entries in table to describe location of boot on disk * written by installboot */struct blktab {	unsigned int	b_blknum:24;	/* starting block number */	unsigned int	b_size:8;	/* number of DEV_BSIZE byte blocks */};struct biblk {	struct blktab 	bi_blks[NDBLKS];	int		bi_size;	int		bi_checksum;} biblk;/* * Transfers must be limited to MAXBSIZE because the bootblk drivers * fail with larger requests. */#define MAX_B_SIZE MAXBSIZE/SECTORSIZE	/* largest value for b_size field above */#ifdef DEBUGchar	tflg = 0;#endif	/* DEBUG */char *malloc();/* VARARGS2 */extern char *sprintf();main(argc, argv)	register int argc;	register char *argv[];{	register int i, bbsize;	register int bfd, pfd, dfd;	/* boot, protoboot, device */	register char *bootfile;	register char *protobootblk;	register char *bootdevice;	char bb[BOOTBLKSIZE + roundup(sizeof(struct exec),SECTORSIZE)];	off_t	seekoff;	if (argc < 4 || argc >5) {#ifdef DEBUG		(void) fprintf(stderr,		"Usage: %s [-vlht] bootfile protobootblk bootdevice\n", *argv);#else		(void) fprintf(stderr,		"Usage: %s [-vlh] bootfile protobootblk bootdevice\n", *argv);#endif	/* DEBUG */		exit(1);	}	/* check arguments */	if (argv[1][0] == '-') {		for (i = 1; argv[1][i]; i++) {			switch (argv[1][i]) {#ifdef DEBUG			case 't':		/* testing */				tflg++;				lflg++;		/* fall through */#endif	/* DEBUG */			case 'v':				vflg++;		/* be verbose */				break;			case 'l':				lflg++;				break;		/* list blocks */			case 'h':				hflg++;				break;		/* don't strip header */			default:				break;			}		}		bootfile = argv[2];		protobootblk = argv[3];		bootdevice = argv[4];	} else {		bootfile = argv[1];		protobootblk = argv[2];		bootdevice = argv[3];	}	if (geteuid() != 0) {		(void) fprintf(stderr, "%s: Not super user\n", *argv);		exit(1);	}	/*	 * make sure the booter is on the disk for getblks()	 * and that the boot program is marked 0400 and owned by root	 */	if ((bfd = open(bootfile, O_RDWR)) == -1) {		perror("bootfile open");		exit(1);	}	if ((fsync(bfd) != 0) ||		/* put it on disk */	    (chown(bootfile, 0, 3) != 0) ||	/* chown root bootfile */	    (chmod(bootfile, 0444) != 0))	/* chmod 444 bootfile */		perror("bootfile sync");	if (vflg) {		(void) printf("Primary boot: %s\n", protobootblk);		(void) printf("Secondary boot: %s\n", bootfile);		(void) printf("Boot device: %s\n", bootdevice);	}#ifdef DEBUG	if (vflg) {		(void) printf("Boot: bzero(0x%x, 0x%x)\n",			&biblk, sizeof (biblk));	}#endif	/* DEBUG */	bzero((char *)&biblk, sizeof (biblk));	getblks(bootfile, bootdevice);	if (lflg) {		(void) printf("Block locations:\n");		(void) printf("startblk size\n");		for (i = 0;		     biblk.bi_blks[i].b_size && biblk.bi_blks[i].b_blknum;		     i++) {			(void) printf("%x\t   %x\n",			    biblk.bi_blks[i].b_blknum, biblk.bi_blks[i].b_size);		}	}	if ((pfd = open(protobootblk, O_RDONLY)) == -1) {		perror("open");		exit(1);	}	bbsize = tdsize(pfd) + (hflg ? sizeof(struct exec) : 0);#ifdef DEBUG	if (tflg) {		(void) printf("Bootblk size (computed): 0x%x\n", bbsize);	}#endif 	/* DEBUG */	if (bbsize > BOOTBLKSIZE) {		(void) printf("%s > 0x%x (0x%x), will not fit in boot block\n",			protobootblk, BOOTBLKSIZE, bbsize);		exit(1);	}	/*	 * Read in the prototype bootblk.   Note that we are	 * assuming that it still has a header. If hflg is false	 * (the default), skip over the header so that we write out	 * a bootblock to the device with no header.	 */	seekoff = (off_t)(hflg ? 0 : sizeof(struct exec));	if (lseek(pfd, seekoff, 0) == (off_t)-1) {		perror("seek protobootblk");		exit(1);	}	if (read(pfd, bb, bbsize) != bbsize) {		perror("read protobootblk");		exit(1);	}	if (close(pfd) != 0)		perror("close protobootblk");#ifdef DEBUG	if (tflg) {		(void) printf("Bootblk size (read): 0x%x\n", bbsize);	}#endif 	/* DEBUG */	if (hflg)		(void) printf("Bootblock will contain a.out header\n");	/*	 * calculate and write a checksum of the real boot program	 * in the bootblk to assure that the blocks that we read in	 * belong to the right boot program	 */	chksum(bfd);	if (close(bfd) != 0)		perror("bootfile close");	if (vflg) {		(void) printf("Boot size: 0x%x\n", biblk.bi_size);		(void) printf("Boot checksum: 0x%x\n", biblk.bi_checksum);	}	/*	 * save the information about the blocks of the real boot	 * into the boot block	 */#ifdef DEBUG	if (vflg) {		(void) printf("Boot: bcopy(0x%x, 0x%x, 0x%x)\n", &biblk,		    bb + sizeof (int) + (hflg ? sizeof (struct exec) : 0),		    sizeof (biblk));	}#endif	/* DEBUG */	bcopy((char *)&biblk,	    bb + sizeof (int) + (hflg ? sizeof (struct exec) : 0),	    sizeof (biblk));#ifdef DEBUG	if (vflg)		(void) printf("Block information written to bootblock\n");	if (tflg)		/* if testing don't write anything */		 exit(0);#endif 	/* DEBUG */	/*	 * open bootdevice file	 */	if ((dfd = open(bootdevice, O_RDWR)) == -1) {		perror("open");		exit(1);	}#ifdef DEBUG	if (vflg)		(void) printf("Boot device opened\n");#endif	/* DEBUG */	if (lseek(dfd, (off_t) SECTORSIZE, 0) == (off_t)-1) {	/* skip label */		perror("seek bootdevice");		exit(1);	}	/*	 * write out the boot block	 */#ifdef DEBUG	if (vflg)	    (void) printf("Boot: write(0x%x, 0x%x, 0x%x)\n", dfd, bb,		roundup(bbsize, SECTORSIZE));#endif	/* DEBUG */	if ((i = write(dfd, bb, roundup(bbsize, SECTORSIZE))) == -1) {		perror("write of boot block failed");		exit(1);	}	if (close(dfd) != 0)		perror("close bootdevice");#ifdef DEBUG	if (vflg)		(void) printf("Bootblock (0x%x bytes) written to device\n", i);#endif	/* DEBUG */	(void) printf("Boot block installed\n");	exit(0);	/* NOTREACHED */}getblks(file, device)	char *file;	char *device;{	register struct	fs *fs;	register struct dinode *dinode;	int	devfd;	int	block;	int	offset;	int	seekaddr;	u_int	*blk;	register int	size;	register int	i, j;	register int	bt;	register int	spf;	register int	fpb;	register int	spb;	struct  stat    statb;	struct	stat	statrd;	struct	stat	statd;	int	inode;	int	indirect;	char	buf[64];	/*	 * check booter	 */	if (stat(file, &statb) == -1) {		(void) fprintf(stderr, "File %s not found\n", file);		exit(1);	}	/* check for zero-length file */	if (statb.st_size <= 0) {		(void) fprintf(stderr,	"File %s is zero-length, no bootblocks installed\n", file);		exit(1);	}	inode = statb.st_ino;	/*	 * check bootdevice	 */	if (stat(device, &statrd) == -1) {		(void) fprintf(stderr,			"bootdevice %s doesn't make sense (couldn't stat)\n",			device);		exit(1);	}	/*	 * check that the device we are going to write is a raw device	 * if it is not raw, give up.	 *	 * block devices are not kept consistent with control information	 * (ie. incore inodes) if you create a file, the block containing	 * the inode will not be updated with the new inode information	 */	if ((statrd.st_mode & S_IFMT) != S_IFCHR) {		(void) fprintf(stderr, "%s not raw device\n", device);		exit(1);	}	/*	 * look for /dev/r____, build name of block device	 * used for booting, check it	 */	if (strncmp(device, "/dev/r", sizeof "/dev/r" - 1) != 0) {		(void) fprintf(stderr,"unexpected bootdevice %s; name must be of the form /dev/r____\n", device);		exit(1);	}	(void)sprintf(buf, "/dev/%s", device + sizeof "/dev/r" - 1);	if (stat(buf, &statd) == -1 || (statd.st_mode & S_IFMT) != S_IFBLK) {		(void) fprintf(stderr,			"couldn't stat block bootdevice %s\n", buf);		exit(1);	}	/*	 * if the file's device (st_dev) == the device's device (st_rdev)	 * the file is on the device	 */	if (statb.st_dev != statd.st_rdev) {		(void) fprintf(stderr,			 "bootfile %s not on bootdevice %s\n", file, device);		exit(1);	}	/*	 * read in and check the superblock	 */	if ((devfd = open(device, O_RDONLY)) == -1) {		perror("Can't open raw device");		exit(1);	}	if (lseek(devfd, (off_t)SUPERADDR, 0) == (off_t)-1) {		perror("Seek to superblock failed");		exit(1);	}	if (read(devfd, (char *)superblock,		roundup(sizeof (struct fs), SECTORSIZE)) == -1) {		perror("Read of superblock failed");		exit(1);	}	fs = (struct fs *)superblock;	if (fs->fs_magic != FS_MAGIC) {		(void) fprintf(stderr, "Not a superblock\n");		exit(1);	}	block = itod(fs, inode);	offset = itoo(fs, inode);	seekaddr = fsbtodb(fs, block) * SECTORSIZE;	/*	 * find the block containing the inode for the bootfile	 */	if (lseek(devfd, (off_t) seekaddr, 0) == (off_t)-1) {		(void) fprintf(stderr, "Seek to block %d offset %d failed\n",			block, offset);		exit(1);	}	if (read(devfd, (char *)ibuf, (int)fs->fs_bsize) == -1) {		(void) fprintf(stderr, "Read of inode %d failed\n", inode);		exit(1);	}	dinode = (struct dinode *)&ibuf			[offset * sizeof (struct dinode) / sizeof (long)];	spf = fs->fs_fsize / SECTORSIZE;	/* sectors per frag */	fpb = fs->fs_bsize / fs->fs_fsize;	/* frags per block */	spb = fpb * spf;			/* sectors per block */	size = dinode->di_size;	/* get first level blocks pointers */	bt = 0;	for (i = 0; (i < NDADDR) && (size > 0); i++) {		u_int	temp_bsize;		/*		 * try to coalesce sequential blocks		 * into a blktab single entry		 */		if (  (bt > 0)		   && ((biblk.bi_blks[bt-1].b_blknum +		        biblk.bi_blks[bt-1].b_size)		        == fsbtodb(fs, dinode->di_db[i]))		   && ((biblk.bi_blks[bt-1].b_size + spb) < MAX_B_SIZE)		     ) { 			temp_bsize = biblk.bi_blks[bt-1].b_size;			biblk.bi_blks[bt-1].b_size = temp_bsize + spb;		} else {			if (bt+1 >= NDBLKS) {				(void)fprintf(stderr,			"The boot program has too many discontinuous blocks\n");				exit(1);			}			biblk.bi_blks[bt].b_blknum =				fsbtodb(fs, dinode->di_db[i]);			biblk.bi_blks[bt].b_size = (spb & 0xff);			bt++;		}		size -= fs->fs_bsize;	}	blk = (u_int *)malloc((unsigned) fs->fs_bsize);	/* now go for indirect blocks */	for (i = 0; (i < NIADDR) && (size > 0); i++) {		indirect = dinode->di_ib[i];		seekaddr = fsbtodb(fs, indirect) * SECTORSIZE;		if (lseek(devfd, (off_t) seekaddr, 0) == (off_t)-1) {			(void) fprintf(stderr,				"Seek to indirect block %d failed\n", indirect);			exit(1);		}		if (read(devfd, (char *)blk, (int) fs->fs_bsize) == -1) {			(void) fprintf(stderr,				"Read of indirect block %d failed\n", indirect);			exit(1);		}		/* save block numbers from indirect blocks */		for (j = 0;		     (j < fs->fs_bsize / sizeof (int)) && (size > 0);		     j++, size -= fs->fs_bsize) {			u_int	temp_bsize;			if (  (bt > 0)			   && ((biblk.bi_blks[bt-1].b_blknum +				biblk.bi_blks[bt-1].b_size)				== fsbtodb(fs, blk[j]))			   && ((biblk.bi_blks[bt-1].b_size + spb) < MAX_B_SIZE)			     ) { 				temp_bsize = biblk.bi_blks[bt-1].b_size;				biblk.bi_blks[bt-1].b_size = temp_bsize + spb;			} else {				if (bt+1 >= NDBLKS) {					(void)fprintf(stderr,			"The boot program has too many discontinuous blocks\n");					exit(1);				}				biblk.bi_blks[bt].b_blknum =				    fsbtodb(fs, blk[j]);				biblk.bi_blks[bt].b_size = (spb & 0xff);				bt++;			}		}	}}/* * read the header of the file and return * the sum of its text and data segments */tdsize(bootfd)	register int bootfd;{	long buf[((sizeof (struct exec) * 2) + 4) / sizeof (long)];	register struct exec *e;	if (read(bootfd, (char *)buf, sizeof (struct exec))== -1) {		(void) printf("trouble reading header\n");	}	e = (struct exec *)buf;#ifdef DEBUG	if (vflg) {		(void) printf("tdsize: text 0x%x data 0x%x\n",			e->a_text, e->a_data);	}#endif	/* DEBUG */	return (e->a_text + e->a_data);}chksum(fd)	register int fd;{	register unsigned int sum;	register int *p;	register int x;	register int size;	static int buf[DEV_BSIZE / sizeof (int)];	/*	 * The boot program loaded by the bootblk should be stripped.	 * We used to enforce that it be headerless as well, but we	 * don't any more; that's the user's problem.	 */	if (lseek(fd, (off_t) 0, 0) != (off_t)0)		perror("seek bootfile");	sum = 0;	size = 0;	bzero ((char *) buf, sizeof buf);	while (x = read(fd, (char *) buf, sizeof buf)) {		size += x;		for (p = buf; x > 0; x -= 4) {			 sum += *p++;		}		bzero ((char *) buf, sizeof buf);	}	biblk.bi_size = size;	biblk.bi_checksum = sum;}

⌨️ 快捷键说明

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