Ejemplo n.º 1
0
static int
loadk(char *file, u_long *marks)
{
    int fd, error, flags;
    vaddr_t va;
    paddr_t pa;
    u_long minsize, size;
    vaddr_t extra;

    /*
     * Regardless of the address where we load the kernel, we need to
     * make sure it has enough valid space to use during pmap_bootstrap.
     * locore.s tries to map the 512KB following the kernel image, and
     * we need to make sure this extra room does not overwrite PROM data
     * (such as the PROM page tables which are immediately below 4MB on
     * most sun4c).
     */
    extra = 512 * 1024;

    if ((fd = open(file, O_RDONLY)) < 0)
        return (errno ? errno : ENOENT);

    /*
     * We need to know whether we are booting off a tape or not,
     * because we can not seek backwards off tapes.
     */

    if (files[fd].f_flags & F_RAW) {
        flags = (COUNT_KERNEL & ~COUNT_SYM) | (LOAD_KERNEL & ~LOAD_SYM);
        minsize = FOURMB;
        va = 0xf8000000;		/* KERNBASE */
#ifdef DEBUG
        printf("Tape boot: expecting a bsd.rd kernel smaller than %p\n",
               minsize);
#endif
        /* compensate for extra room below */
        minsize -= extra;
    } else {
        /*
         * If we did not load a random.seed file yet, try and load
         * one.
         */
        if (rnd_loaded == 0) {
            /*
             * Some PROM do not like having a network device
             * open()ed twice; better close and reopen after
             * trying to get randomness.
             */
            close(fd);

            rnd_loaded = loadrandom(BOOTRANDOM, rnddata,
                                    sizeof(rnddata));

            if ((fd = open(file, O_RDONLY)) < 0)
                return (errno ? errno : ENOENT);
        }

        flags = LOAD_KERNEL;
        marks[MARK_START] = 0;

        /*
         * Even though we just have opened the file, the gzip code
         * has tried to read from it. Be sure to reset position in
         * case the file is not compressed (transparent mode isn't
         * so transparent...)
         */
        if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
            error = errno;
            goto out;
        }

        if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0)
            goto out;

        /* rewind file for the actual load operation later */
        if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
            error = errno;
            goto out;
        }

        minsize = marks[MARK_END] - marks[MARK_START];

        /* We want that leading 16K in front of the kernel image */
        minsize += PROM_LOADADDR;
        va = marks[MARK_START] - PROM_LOADADDR;
    }

    /*
     * If the kernel would entirely fit under the boot code, and the
     * boot code has been loaded 1:1, we do not need to allocate
     * breathing room after it.
     */
    size = minsize + extra;
    if (compat != 0) {
        if (minsize + extra <= RELOC2 - LOWSTACK)
            size = RELOC2 - LOWSTACK;
        else
            compat = 0;
    }

    /* Get a physical load address */
#ifdef DEBUG
    printf("kernel footprint %p, requesting %p\n", minsize, size);
#endif
    pa = getphysmem(size);
    if (pa == (paddr_t)-1) {
        /*
         * The extra bootstrap memory estimate might have been
         * too much, if physical memory doesn't have any contiguous
         * large chunks (e.g. on sun4c systems with 4MB regions).
         * If that increase caused us to cross a 4MB boundary, try
         * to limit ourselves to a 4MB multiple.
         */
        if (compat == 0 && size / FOURMB != minsize / FOURMB) {
            size = roundup(minsize, FOURMB);
#ifdef DEBUG
            printf("now trying %p\n", size);
#endif
            pa = getphysmem(size);
        }
        if (pa == (paddr_t)-1) {
            error = EFBIG;
            goto out;
        }
    }

    printf("Loading at physical address %lx\n", pa);
    if (pmap_map(va, pa, size) != 0) {
        error = EFAULT;
        goto out;
    }

    /* try and double-map at VA 0 for compatibility */
    if (pa + size > bstart) {
#ifdef DEBUG
        printf("WARNING: %s is too large for compat mode.\n"
               "If your kernel is too old, it will not run correctly.\n",
               file);
#endif
    } else {
        if (pa != 0 && pmap_map(0, pa, size) != 0) {
            error = EFAULT;
            goto out;
        }
    }

    marks[MARK_START] = 0;
    error = fdloadfile(fd, marks, flags);
out:
    close(fd);
    return (error);
}
Ejemplo n.º 2
0
int
main(int argc, char *argv[])
{
	int ch;
	struct partition *pp;
	struct disklabel *lp;
	struct partition oldpartition;
	struct stat st;
	struct statfs *mp;
	struct rlimit rl;
	int fsi = -1, fso, len, n, maxpartitions;
	char *cp = NULL, *s1, *s2, *special, *opstring, *realdev;
	char *fstype = NULL;
	char **saveargv = argv;
	int ffsflag = 1;
	const char *errstr;
	long long fssize_input = 0;
	int fssize_usebytes = 0;
	u_int64_t nsecs;

	getphysmem();
	maxpartitions = getmaxpartitions();
	if (maxpartitions > 26)
		fatal("insane maxpartitions value %d", maxpartitions);

	opstring = "NO:S:T:b:c:e:f:g:h:i:m:o:qs:t:";
	while ((ch = getopt(argc, argv, opstring)) != -1) {
		switch (ch) {
		case 'N':
			Nflag = 1;
			break;
		case 'O':
			Oflag = strtonum(optarg, 0, 2, &errstr);
			if (errstr)
				fatal("%s: invalid ffs version", optarg);
			break;
		case 'S':
			if (scan_scaled(optarg, &sectorsize) == -1 ||
			    sectorsize <= 0 || (sectorsize % DEV_BSIZE))
				fatal("sector size invalid: %s", optarg);
			break;
		case 'T':
			disktype = optarg;
			break;
		case 'b':
			bsize = strtonum(optarg, MINBSIZE, MAXBSIZE, &errstr);
			if (errstr)
				fatal("block size is %s: %s", errstr, optarg);
			break;
		case 'c':
			maxfrgspercg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("fragments per cylinder group is %s: %s",
				    errstr, optarg);
			break;
		case 'e':
			maxbpg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("blocks per file in a cylinder group is"
				    " %s: %s", errstr, optarg);
			break;
		case 'f':
			fsize = strtonum(optarg, MINBSIZE / MAXFRAG, MAXBSIZE,
			    &errstr);
			if (errstr)
				fatal("fragment size is %s: %s",
				    errstr, optarg);
			break;
		case 'g':
			avgfilesize = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average file size is %s: %s",
				    errstr, optarg);
			break;
		case 'h':
			avgfilesperdir = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average files per dir is %s: %s",
				    errstr, optarg);
			break;
		case 'i':
			density = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("bytes per inode is %s: %s",
				    errstr, optarg);
			break;
		case 'm':
			minfree = strtonum(optarg, 0, 99, &errstr);
			if (errstr)
				fatal("free space %% is %s: %s",
				    errstr, optarg);
			break;
		case 'o':
			if (strcmp(optarg, "space") == 0)
				reqopt = opt = FS_OPTSPACE;
			else if (strcmp(optarg, "time") == 0)
				reqopt = opt = FS_OPTTIME;
			else
				fatal("%s: unknown optimization preference: "
				    "use `space' or `time'.", optarg);
			break;
		case 'q':
			quiet = 1;
			break;
		case 's':
			if (scan_scaled(optarg, &fssize_input) == -1 ||
			    fssize_input == 0)
				fatal("file system size invalid: %s", optarg);
			fssize_usebytes = 0;    /* in case of multiple -s */
			for (s1 = optarg; *s1 != '\0'; s1++)
				if (isalpha((unsigned char)*s1)) {
					fssize_usebytes = 1;
					break;
				}
			break;
		case 't':
			fstype = optarg;
			if (strcmp(fstype, "ffs"))
				ffsflag = 0;
			break;
		case '?':
		default:
			usage();
		}
		if (!ffsflag)
			break;
	}
	argc -= optind;
	argv += optind;

	if (ffsflag && argc != 1)
		usage();

	special = argv[0];

	char execname[MAXPATHLEN], name[MAXPATHLEN];

	if (fstype == NULL)
		fstype = readlabelfs(special, 0);
	if (fstype != NULL && strcmp(fstype, "ffs")) {
		snprintf(name, sizeof name, "newfs_%s", fstype);
		saveargv[0] = name;
		snprintf(execname, sizeof execname, "%s/newfs_%s", _PATH_SBIN,
		    fstype);
		(void)execv(execname, saveargv);
		snprintf(execname, sizeof execname, "%s/newfs_%s",
		    _PATH_USRSBIN, fstype);
		(void)execv(execname, saveargv);
		err(1, "%s not found", name);
	}

	if (Nflag) {
		fso = -1;
	} else {
		fso = opendev(special, O_WRONLY, 0, &realdev);
		if (fso < 0)
			fatal("%s: %s", special, strerror(errno));
		special = realdev;

		/* Bail if target special is mounted */
		n = getmntinfo(&mp, MNT_NOWAIT);
		if (n == 0)
			fatal("%s: getmntinfo: %s", special, strerror(errno));

		len = sizeof(_PATH_DEV) - 1;
		s1 = special;
		if (strncmp(_PATH_DEV, s1, len) == 0)
			s1 += len;

		while (--n >= 0) {
			s2 = mp->f_mntfromname;
			if (strncmp(_PATH_DEV, s2, len) == 0) {
				s2 += len - 1;
				*s2 = 'r';
			}
			if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
				fatal("%s is mounted on %s",
				    special, mp->f_mntonname);
			++mp;
		}
	}
	fsi = opendev(special, O_RDONLY, 0, NULL);
	if (fsi < 0)
		fatal("%s: %s", special, strerror(errno));
	if (fstat(fsi, &st) < 0)
		fatal("%s: %s", special, strerror(errno));
	if (S_ISBLK(st.st_mode))
		fatal("%s: block device", special);
	if (!S_ISCHR(st.st_mode))
		warnx("%s: not a character-special device",
		    special);
	if (*argv[0] == '\0')
		fatal("empty partition name supplied");
	cp = argv[0] + strlen(argv[0]) - 1;
	if ((*cp < 'a' || *cp > ('a' + maxpartitions - 1))
	    && !isdigit((unsigned char)*cp))
		fatal("%s: can't figure out file system partition",
		    argv[0]);
	lp = getdisklabel(special, fsi);
	if (pledge("stdio disklabel tty", NULL) == -1)
		err(1, "pledge");
	if (isdigit((unsigned char)*cp))
		pp = &lp->d_partitions[0];
	else
		pp = &lp->d_partitions[*cp - 'a'];
	if (DL_GETPSIZE(pp) == 0)
		fatal("%s: `%c' partition is unavailable",
		    argv[0], *cp);
	if (pp->p_fstype == FS_BOOT)
		fatal("%s: `%c' partition overlaps boot program",
		      argv[0], *cp);
havelabel:
	if (sectorsize == 0) {
		sectorsize = lp->d_secsize;
		if (sectorsize <= 0)
			fatal("%s: no default sector size", argv[0]);
	}

	if (fssize_input < 0) {
#if 1
		fatal("-s < 0 not yet implemented");
#else
		long long gap; /* leave gap at the end of partition */
		fssize_input = -fssize_input;
		if (fssize_usebytes) {
			gap = (daddr_t)fssize_input / (daddr_t)sectorsize;
			if ((daddr_t)fssize_input % (daddr_t)sectorsize != 0)
				gap++;
		} else
			gap = fssize_input;
		if (gap >= DL_GETPSIZE(pp))
			fatal("%s: requested gap of %lld sectors on partition "
			    "'%c' is too big", argv[0], gap, *cp);
		nsecs = DL_GETPSIZE(pp) - gap;
#endif
	} else {
		if (fssize_usebytes) {
			nsecs = fssize_input / sectorsize;
			if (fssize_input % sectorsize != 0)
				nsecs++;
		} else if (fssize_input == 0)
			nsecs = DL_GETPSIZE(pp);
		else
			nsecs = fssize_input;
	}

	if (nsecs > DL_GETPSIZE(pp))
	       fatal("%s: maximum file system size on the `%c' partition is "
		   "%llu sectors", argv[0], *cp, DL_GETPSIZE(pp));

	/* Can't use DL_SECTOBLK() because sectorsize may not be from label! */
	fssize = nsecs * (sectorsize / DEV_BSIZE);
	if (fsize == 0) {
		fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock);
		if (fsize <= 0)
			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
	}
	if (bsize == 0) {
		bsize = DISKLABELV1_FFS_BSIZE(pp->p_fragblock);
		if (bsize <= 0)
			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
	}
	if (density == 0)
		density = NFPI * fsize;
	if (minfree < MINFREE && opt != FS_OPTSPACE && reqopt == -1) {
		warnx("warning: changing optimization to space "
		    "because minfree is less than %d%%\n", MINFREE);
		opt = FS_OPTSPACE;
	}
	if (maxbpg == 0) {
		if (Oflag <= 1)
			maxbpg = MAXBLKPG_FFS1(bsize);
		else
			maxbpg = MAXBLKPG_FFS2(bsize);
	}
	oldpartition = *pp;

	mkfs(pp, special, fsi, fso);
	if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)))
		rewritelabel(special, fso, lp);
	if (!Nflag)
		close(fso);
	close(fsi);
	exit(0);
}
Ejemplo n.º 3
0
int
main(int argc, char *argv[])
{
	int ch;
	struct partition *pp;
	struct disklabel *lp;
	struct disklabel mfsfakelabel;
	struct partition oldpartition;
	struct stat st;
	struct statfs *mp;
	struct rlimit rl;
	int fsi = -1, oflagset = 0, fso, len, n, maxpartitions;
	char *cp = NULL, *s1, *s2, *special, *opstring, *realdev;
#ifdef MFS
	char mountfromname[BUFSIZ];
	char *pop = NULL, node[PATH_MAX];
	pid_t pid, res;
	struct statfs sf;
	struct stat mountpoint;
	int status;
#endif
	uid_t mfsuid = 0;
	gid_t mfsgid = 0;
	mode_t mfsmode = 0;
	char *fstype = NULL;
	char **saveargv = argv;
	int ffsflag = 1;
	const char *errstr;
	long long fssize_input = 0;
	int fssize_usebytes = 0;
	u_int64_t nsecs;

	if (strstr(__progname, "mfs"))
		mfs = Nflag = quiet = 1;

	getphysmem();
	maxpartitions = getmaxpartitions();
	if (maxpartitions > 26)
		fatal("insane maxpartitions value %d", maxpartitions);

	opstring = mfs ?
	    "P:T:b:c:e:f:i:m:o:s:" :
	    "NO:S:T:b:c:e:f:g:h:i:m:o:qs:t:";
	while ((ch = getopt(argc, argv, opstring)) != -1) {
		switch (ch) {
		case 'N':
			Nflag = 1;
			break;
		case 'O':
			Oflag = strtonum(optarg, 0, 2, &errstr);
			if (errstr)
				fatal("%s: invalid ffs version", optarg);
			oflagset = 1;
			break;
		case 'S':
			if (scan_scaled(optarg, &sectorsize) == -1 ||
			    sectorsize <= 0 || (sectorsize % DEV_BSIZE))
				fatal("sector size invalid: %s", optarg);
			break;
		case 'T':
			disktype = optarg;
			break;
		case 'b':
			bsize = strtonum(optarg, MINBSIZE, MAXBSIZE, &errstr);
			if (errstr)
				fatal("block size is %s: %s", errstr, optarg);
			break;
		case 'c':
			maxfrgspercg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("fragments per cylinder group is %s: %s",
				    errstr, optarg);
			break;
		case 'e':
			maxbpg = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("blocks per file in a cylinder group is"
				    " %s: %s", errstr, optarg);
			break;
		case 'f':
			fsize = strtonum(optarg, MINBSIZE / MAXFRAG, MAXBSIZE,
			    &errstr);
			if (errstr)
				fatal("fragment size is %s: %s",
				    errstr, optarg);
			break;
		case 'g':
			avgfilesize = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average file size is %s: %s",
				    errstr, optarg);
			break;
		case 'h':
			avgfilesperdir = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("average files per dir is %s: %s",
				    errstr, optarg);
			break;
		case 'i':
			density = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				fatal("bytes per inode is %s: %s",
				    errstr, optarg);
			break;
		case 'm':
			minfree = strtonum(optarg, 0, 99, &errstr);
			if (errstr)
				fatal("free space %% is %s: %s",
				    errstr, optarg);
			break;
		case 'o':
			if (mfs)
				getmntopts(optarg, mopts, &mntflags);
			else {
				if (strcmp(optarg, "space") == 0)
					reqopt = opt = FS_OPTSPACE;
				else if (strcmp(optarg, "time") == 0)
					reqopt = opt = FS_OPTTIME;
				else
					fatal("%s: unknown optimization "
					    "preference: use `space' or `time'.",
					    optarg);
			}
			break;
		case 'q':
			quiet = 1;
			break;
		case 's':
			if (scan_scaled(optarg, &fssize_input) == -1 ||
			    fssize_input <= 0)
				fatal("file system size invalid: %s", optarg);
			fssize_usebytes = 0;    /* in case of multiple -s */
			for (s1 = optarg; *s1 != '\0'; s1++)
				if (isalpha((unsigned char)*s1)) {
					fssize_usebytes = 1;
					break;
				}
			break;
		case 't':
			fstype = optarg;
			if (strcmp(fstype, "ffs"))
				ffsflag = 0;
			break;
#ifdef MFS
		case 'P':
			pop = optarg;
			break;
#endif
		case '?':
		default:
			usage();
		}
		if (!ffsflag)
			break;
	}
	argc -= optind;
	argv += optind;

	if (ffsflag && argc - mfs != 1)
		usage();

	if (mfs) {
		/* Increase our data size to the max */
		if (getrlimit(RLIMIT_DATA, &rl) == 0) {
			rl.rlim_cur = rl.rlim_max;
			(void)setrlimit(RLIMIT_DATA, &rl);
		}
	}

	special = argv[0];

	if (!mfs) {
		char execname[PATH_MAX], name[PATH_MAX];

		if (fstype == NULL)
			fstype = readlabelfs(special, 0);
		if (fstype != NULL && strcmp(fstype, "ffs")) {
			snprintf(name, sizeof name, "newfs_%s", fstype);
			saveargv[0] = name;
			snprintf(execname, sizeof execname, "%s/newfs_%s",
			    _PATH_SBIN, fstype);
			(void)execv(execname, saveargv);
			snprintf(execname, sizeof execname, "%s/newfs_%s",
			    _PATH_USRSBIN, fstype);
			(void)execv(execname, saveargv);
			err(1, "%s not found", name);
		}
	}

	if (mfs && !strcmp(special, "swap")) {
		/*
		 * it's an MFS, mounted on "swap."  fake up a label.
		 * XXX XXX XXX
		 */
		fso = -1;	/* XXX; normally done below. */

		memset(&mfsfakelabel, 0, sizeof(mfsfakelabel));
		mfsfakelabel.d_secsize = 512;
		mfsfakelabel.d_nsectors = 64;
		mfsfakelabel.d_ntracks = 16;
		mfsfakelabel.d_ncylinders = 16;
		mfsfakelabel.d_secpercyl = 1024;
		DL_SETDSIZE(&mfsfakelabel, 16384);
		mfsfakelabel.d_npartitions = 1;
		mfsfakelabel.d_version = 1;
		DL_SETPSIZE(&mfsfakelabel.d_partitions[0], 16384);
		mfsfakelabel.d_partitions[0].p_fragblock =
		    DISKLABELV1_FFS_FRAGBLOCK(1024, 8);
		mfsfakelabel.d_partitions[0].p_cpg = 16;

		lp = &mfsfakelabel;
		pp = &mfsfakelabel.d_partitions[0];

		goto havelabel;
	}
	if (Nflag) {
		fso = -1;
	} else {
		fso = opendev(special, O_WRONLY, 0, &realdev);
		if (fso < 0)
			fatal("%s: %s", special, strerror(errno));
		special = realdev;

		/* Bail if target special is mounted */
		n = getmntinfo(&mp, MNT_NOWAIT);
		if (n == 0)
			fatal("%s: getmntinfo: %s", special, strerror(errno));

		len = sizeof(_PATH_DEV) - 1;
		s1 = special;
		if (strncmp(_PATH_DEV, s1, len) == 0)
			s1 += len;

		while (--n >= 0) {
			s2 = mp->f_mntfromname;
			if (strncmp(_PATH_DEV, s2, len) == 0) {
				s2 += len - 1;
				*s2 = 'r';
			}
			if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
				fatal("%s is mounted on %s",
				    special, mp->f_mntonname);
			++mp;
		}
	}
	if (mfs && disktype != NULL) {
		lp = (struct disklabel *)getdiskbyname(disktype);
		if (lp == NULL)
			fatal("%s: unknown disk type", disktype);
		pp = &lp->d_partitions[1];
	} else {
		fsi = opendev(special, O_RDONLY, 0, NULL);
		if (fsi < 0)
			fatal("%s: %s", special, strerror(errno));
		if (fstat(fsi, &st) < 0)
			fatal("%s: %s", special, strerror(errno));
		if (!mfs) {
			if (S_ISBLK(st.st_mode))
				fatal("%s: block device", special);
			if (!S_ISCHR(st.st_mode))
				warnx("%s: not a character-special device",
				    special);
		}
		if (*argv[0] == '\0')
			fatal("empty partition name supplied");
		cp = argv[0] + strlen(argv[0]) - 1;
		if ((*cp < 'a' || *cp > ('a' + maxpartitions - 1))
		    && !isdigit((unsigned char)*cp))
			fatal("%s: can't figure out file system partition",
			    argv[0]);
		lp = getdisklabel(special, fsi);
		if (!mfs) {
			if (pledge("stdio disklabel tty", NULL) == -1)
				err(1, "pledge");
		}
		if (isdigit((unsigned char)*cp))
			pp = &lp->d_partitions[0];
		else
			pp = &lp->d_partitions[*cp - 'a'];
		if (DL_GETPSIZE(pp) == 0)
			fatal("%s: `%c' partition is unavailable",
			    argv[0], *cp);
		if (pp->p_fstype == FS_BOOT)
			fatal("%s: `%c' partition overlaps boot program",
			      argv[0], *cp);
	}
havelabel:
	if (sectorsize == 0) {
		sectorsize = lp->d_secsize;
		if (sectorsize <= 0)
			fatal("%s: no default sector size", argv[0]);
	}

	if (fssize_usebytes) {
		nsecs = fssize_input / sectorsize;
		if (fssize_input % sectorsize != 0)
			nsecs++;
	} else if (fssize_input == 0)
		nsecs = DL_GETPSIZE(pp);
	else
		nsecs = fssize_input;

	if (nsecs > DL_GETPSIZE(pp) && !mfs)
	       fatal("%s: maximum file system size on the `%c' partition is "
		   "%llu sectors", argv[0], *cp, DL_GETPSIZE(pp));

	/* Can't use DL_SECTOBLK() because sectorsize may not be from label! */
	fssize = nsecs * (sectorsize / DEV_BSIZE);
	if (oflagset == 0 && fssize >= INT_MAX)
		Oflag = 2;	/* FFS2 */
	if (fsize == 0) {
		fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock);
		if (fsize <= 0)
			fsize = MAXIMUM(DFL_FRAGSIZE, lp->d_secsize);
	}
	if (bsize == 0) {
		bsize = DISKLABELV1_FFS_BSIZE(pp->p_fragblock);
		if (bsize <= 0)
			bsize = MINIMUM(DFL_BLKSIZE, 8 * fsize);
	}
	if (density == 0)
		density = NFPI * fsize;
	if (minfree < MINFREE && opt != FS_OPTSPACE && reqopt == -1) {
		warnx("warning: changing optimization to space "
		    "because minfree is less than %d%%\n", MINFREE);
		opt = FS_OPTSPACE;
	}
	if (maxbpg == 0) {
		if (Oflag <= 1)
			maxbpg = MAXBLKPG_FFS1(bsize);
		else
			maxbpg = MAXBLKPG_FFS2(bsize);
	}
	oldpartition = *pp;
#ifdef MFS
	if (mfs) {
		if (realpath(argv[1], node) == NULL)
			err(1, "realpath %s", argv[1]);
		if (stat(node, &mountpoint) < 0)
			err(ECANCELED, "stat %s", node);
		mfsuid = mountpoint.st_uid;
		mfsgid = mountpoint.st_gid;
		mfsmode = mountpoint.st_mode & ALLPERMS;
	}
#endif

	mkfs(pp, special, fsi, fso, mfsmode, mfsuid, mfsgid);
	if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)))
		rewritelabel(special, fso, lp);
	if (!Nflag)
		close(fso);
	close(fsi);
#ifdef MFS
	if (mfs) {
		struct mfs_args args;
		memset(&args, 0, sizeof(args));
		args.base = membase;
		args.size = fssize * DEV_BSIZE;
		args.export_info.ex_root = -2;
		if (mntflags & MNT_RDONLY)
			args.export_info.ex_flags = MNT_EXRDONLY;

		switch (pid = fork()) {
		case -1:
			err(10, "mfs");
		case 0:
			snprintf(mountfromname, sizeof(mountfromname),
			    "mfs:%d", getpid());
			break;
		default:
			snprintf(mountfromname, sizeof(mountfromname),
			    "mfs:%d", pid);
			for (;;) {
				/*
				 * spin until the mount succeeds
				 * or the child exits
				 */
				usleep(1);

				/*
				 * XXX Here is a race condition: another process
				 * can mount a filesystem which hides our
				 * ramdisk before we see the success.
				 */
				if (statfs(node, &sf) < 0)
					err(ECANCELED, "statfs %s", node);
				if (!strcmp(sf.f_mntfromname, mountfromname) &&
				    !strncmp(sf.f_mntonname, node,
					     MNAMELEN) &&
				    !strcmp(sf.f_fstypename, "mfs")) {
					if (pop != NULL)
						copy(pop, node, &args);
					exit(0);
				}
				res = waitpid(pid, &status, WNOHANG);
				if (res == -1)
					err(EDEADLK, "waitpid");
				if (res != pid)
					continue;
				if (WIFEXITED(status)) {
					if (WEXITSTATUS(status) == 0)
						exit(0);
					errx(1, "%s: mount: %s", node,
					     strerror(WEXITSTATUS(status)));
				} else
					errx(EDEADLK, "abnormal termination");
			}
			/* NOTREACHED */
		}

		(void) setsid();
		(void) close(0);
		(void) close(1);
		(void) close(2);
		(void) chdir("/");

		args.fspec = mountfromname;
		if (mntflags & MNT_RDONLY && pop != NULL)
			mntflags &= ~MNT_RDONLY;
		if (mount(MOUNT_MFS, node, mntflags, &args) < 0)
			exit(errno); /* parent prints message */
	}
#endif
	exit(0);
}
Ejemplo n.º 4
0
int
main(int argc, char *argv[])
{
	int ch, f, error = 0;
	FILE *t;
	char *autotable = NULL;

	getphysmem();

	while ((ch = getopt(argc, argv, "AEf:F:hRcdenp:tT:vw")) != -1)
		switch (ch) {
		case 'A':
			aflag = 1;
			break;
		case 'R':
			if (op != UNSPEC)
				usage();
			op = RESTORE;
			break;
		case 'c':
			cflag = 1;
			break;
		case 'd':
			dflag = 1;
			break;
		case 'e':
			if (op != UNSPEC)
				usage();
			op = EDIT;
			break;
		case 'E':
			if (op != UNSPEC)
				usage();
			op = EDITOR;
			break;
		case 'f':
			fstabfile = optarg;
			uidflag = 0;
			break;
		case 'F':
			fstabfile = optarg;
			uidflag = 1;
			break;
		case 'h':
			print_unit = '*';
			break;
		case 't':
			tflag = 1;
			break;
		case 'T':
			autotable = optarg;
			break;
		case 'w':
			if (op != UNSPEC)
				usage();
			op = WRITE;
			break;
		case 'p':
			if (strchr("bckmgtBCKMGT", optarg[0]) == NULL ||
			    optarg[1] != '\0') {
				fprintf(stderr, "Valid units are bckmgt\n");
				return 1;
			}
			print_unit = tolower((unsigned char)optarg[0]);
			break;
		case 'n':
			donothing = 1;
			break;
		case 'v':
			verbose = 1;
			break;
		case '?':
		default:
			usage();
	}
	argc -= optind;
	argv += optind;

	if (op == UNSPEC)
		op = READ;

	if (argc < 1 || (fstabfile && !(op == EDITOR || op == RESTORE ||
		    aflag)))
		usage();

	if (argv[0] == NULL)
		usage();
	dkname = argv[0];
	f = opendev(dkname, (op == READ ? O_RDONLY : O_RDWR), OPENDEV_PART,
	    &specname);
	if (f < 0)
		err(4, "%s", specname);

	if (op != WRITE || aflag || dflag) {
		readlabel(f);

		if (op == EDIT || op == EDITOR || aflag) {
			if (pledge("stdio rpath wpath cpath disklabel proc "
			    "exec", NULL) == -1)
				err(1, "pledge");
		} else if (fstabfile) {
			if (pledge("stdio rpath wpath cpath disklabel", NULL)
			    == -1)
				err(1, "pledge");
		} else {
			if (pledge("stdio rpath wpath disklabel", NULL) == -1)
				err(1, "pledge");
		}

		if (autotable != NULL)
			parse_autotable(autotable);
		parselabel();
	} else if (argc == 2 || argc == 3) {
		/* Ensure f is a disk device before pledging. */
		if (ioctl(f, DIOCGDINFO, &lab) < 0)
			err(4, "ioctl DIOCGDINFO");

		if (pledge("stdio rpath wpath disklabel", NULL) == -1)
			err(1, "pledge");

		makelabel(argv[1], argc == 3 ? argv[2] : NULL, &lab);
	} else
		usage();

	switch (op) {
	case EDIT:
		if (argc != 1)
			usage();
		error = edit(&lab, f);
		break;
	case EDITOR:
		if (argc != 1)
			usage();
		error = editor(f);
		break;
	case READ:
		if (argc != 1)
			usage();

		if (pledge("stdio", NULL) == -1)
			err(1, "pledge");

		if (tflag)
			makedisktab(stdout, &lab);
		else
			display(stdout, &lab, print_unit, 1);
		error = checklabel(&lab);
		break;
	case RESTORE:
		if (argc < 2 || argc > 3)
			usage();
		if (!(t = fopen(argv[1], "r")))
			err(4, "%s", argv[1]);
		error = getasciilabel(t, &lab);
		memset(&lab.d_uid, 0, sizeof(lab.d_uid));
		if (error == 0) {
			error = writelabel(f, &lab);
			if (error == 0) {
				if (ioctl(f, DIOCGDINFO, &lab) < 0)
					err(4, "ioctl DIOCGDINFO");
				mpsave(&lab);
			}
		}
		fclose(t);
		break;
	case WRITE:
		error = checklabel(&lab);
		if (error == 0)
			error = writelabel(f, &lab);
		break;
	default:
		break;
	}
	return error;
}
Ejemplo n.º 5
0
static int
loadk(char *kernel, u_long *marks)
{
	int fd, error;
	vaddr_t va;
	paddr_t pa;
	u_long size;
	int flags = LOAD_KERNEL;

	if ((fd = open(kernel, 0)) < 0)
		return (errno ? errno : ENOENT);

	marks[MARK_START] = 0;
	if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0)
		goto out;

	size = marks[MARK_END] - marks[MARK_START];

	/* We want that leading 16K in front of the kernel image */
	size += PROM_LOADADDR;
	va = marks[MARK_START] - PROM_LOADADDR;

	/*
	 * Extra space for bootinfo and kernel bootstrap.
	 * In compat mode, we get to re-use the space occupied by the
	 * boot program. Traditionally, we've silently assumed that
	 * is enough for the kernel to work with.
	 */
	size += BOOTINFO_SIZE;
	if (!compatmode)
		size += 512 * 1024;

	/* Get a physical load address */
	pa = getphysmem(size);
	if (pa == (paddr_t)-1) {
		error = EFBIG;
		goto out;
	}

	if (boothowto & AB_VERBOSE)
		printf("Loading at physical address %lx\n", pa);
	if (pmap_map(va, pa, size) != 0) {
		error = EFAULT;
		goto out;
	}

	/* XXX - to do: inspect kernel image and set compat mode */
	if (compatmode) {
		/* Double-map at VA 0 for compatibility */
		if (pa + size >= bstart) {
			printf("%s: too large for compat mode\n", kernel);
			error = EFBIG;
			goto out;
		}

		if (pa != 0 && pmap_map(0, pa, size) != 0) {
			error = EFAULT;
			goto out;
		}
		loadaddrmask = 0x07ffffffUL;
	}

	if (bootdev_isfloppy(prom_bootdevice))
		flags &= ~LOAD_BACKWARDS;

	marks[MARK_START] = 0;
	error = fdloadfile(fd, marks, flags);
out:
	close(fd);
	return (error);
}