/* * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1997 Tobias Weingartner * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Tobias Weingartner. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "disk.h" #include "user.h" #include "auto.h" #define _PATH_MBR "/usr/standalone/i386/boot0" void usage() { extern char * __progname; fprintf(stderr, "usage: %s " "[-ieu] [-f mbrboot] [-c cyl -h head -s sect] [-S size] [-r] [-a style] disk\n" "\t-i: initialize disk with new MBR\n" "\t-u: update MBR code, preserve partition table\n" "\t-e: edit MBRs on disk interactively\n" "\t-f: specify non-standard MBR template\n" "\t-chs: specify disk geometry\n" "\t-S: specify disk size\n" "\t-r: read partition specs from stdin (implies -i)\n" "\t-a: auto-partition with the given style\n" "\t-d: dump partition table\n" "\t-y: don't ask any questions\n" "\t-t: test if disk is partitioned\n" "`disk' is of the form /dev/rdisk0.\n", __progname); fprintf(stderr, "auto-partition styles:\n"); AUTO_print_styles(stderr); exit(1); } char *mbr_binary = NULL; int main(argc, argv) int argc; char **argv; { int ch, fd; int i_flag = 0, m_flag = 0, u_flag = 0, r_flag = 0, d_flag = 0, y_flag = 0, t_flag = 0; int c_arg = 0, h_arg = 0, s_arg = 0; int size_arg = 0; int block_size_arg = 0; disk_t disk; DISK_metrics *usermetrics; char *mbrfile = _PATH_MBR; mbr_t *mp; char *auto_style = NULL; while ((ch = getopt(argc, argv, "ieuf:c:h:s:b:S:ra:dyt")) != -1) { switch(ch) { case 'i': i_flag = 1; break; case 'u': u_flag = 1; break; case 'e': m_flag = 1; break; case 'f': mbrfile = optarg; break; case 'c': c_arg = atoi(optarg); if (c_arg < 1 || c_arg > 262144) errx(1, "Cylinder argument out of range."); break; case 'h': h_arg = atoi(optarg); if (h_arg < 1 || h_arg > 256) errx(1, "Head argument out of range."); break; case 's': s_arg = atoi(optarg); if (s_arg < 1 || s_arg > 63) errx(1, "Sector argument out of range."); break; case 'b': block_size_arg = atoi(optarg); if (block_size_arg & (block_size_arg - 1)) errx(1, "Block size argument not a power of two."); if (block_size_arg < 512 || block_size_arg > 4096) errx(1, "Block size argument out of range 512..4096."); break; case 'S': size_arg = atoi(optarg); break; case 'r': r_flag = 1; break; case 'a': auto_style = optarg; break; case 'd': d_flag = 1; break; case 'y': y_flag = 1; break; case 't': t_flag = 1; break; default: usage(); } } argc -= optind; argv += optind; /* Argument checking */ if (argc != 1) usage(); else disk.name = argv[0]; if (i_flag && u_flag) errx(1, "-i and -u cannot be specified simultaneously"); /* Put in supplied geometry if there */ if (c_arg | h_arg | s_arg | size_arg | block_size_arg) { usermetrics = malloc(sizeof(DISK_metrics)); if (usermetrics != NULL) { if (c_arg && h_arg && s_arg) { usermetrics->cylinders = c_arg; usermetrics->heads = h_arg; usermetrics->sectors = s_arg; if (size_arg) { usermetrics->size = size_arg; } else { usermetrics->size = c_arg * h_arg * s_arg; } } else { if (size_arg) { usermetrics->size = size_arg; DISK_fake_CHS(usermetrics); } else { errx(1, "Please specify a full geometry with [-chs]."); } } if (block_size_arg) { usermetrics->sector_size = block_size_arg; } else { DISK_get_sector_size(&disk, usermetrics); } } } else { usermetrics = NULL; } /* Get the geometry */ disk.real = NULL; if (DISK_getmetrics(&disk, usermetrics)) errx(1, "Can't get disk geometry, please use [-chs] to specify."); /* If only testing, read MBR and silently exit */ if (t_flag) { mbr_t *mbr; mp = mbr = MBR_read_all(&disk); while (mp) { if (mp->signature != MBR_SIGNATURE) { MBR_free(mbr); exit(1); } mp = mp->next; } MBR_free(mbr); exit(0); } /* If not editing the disk, print out current MBRs on disk */ if ((i_flag + r_flag + u_flag + m_flag) == 0) { exit(USER_print_disk(&disk, d_flag)); } /* Parse mbr template or read partition specs, to pass on later */ if (auto_style && r_flag) { errx(1, "Can't specify both -r and -a"); } mbr_binary = (char *)malloc(MBR_CODE_SIZE); if ((fd = open(mbrfile, O_RDONLY)) == -1) { warn("could not open MBR file %s", mbrfile); bzero(mbr_binary, MBR_CODE_SIZE); } else { int cc; cc = read(fd, mbr_binary, MBR_CODE_SIZE); if (cc < MBR_CODE_SIZE) { err(1, "could not read MBR code"); } close(fd); } if (u_flag) { /* Don't hose the partition table; just write the boot code */ mp = MBR_read_all(&disk); bcopy(mbr_binary, mp->code, MBR_CODE_SIZE); MBR_make(mp); } else if (i_flag) { /* If they didn't specify -a, they'll get the default auto style */ mp = MBR_alloc(NULL); if (AUTO_init(&disk, auto_style, mp) != AUTO_OK) { errx(1, "error initializing disk"); } bcopy(mbr_binary, mp->code, MBR_CODE_SIZE); MBR_make(mp); } else if (r_flag) { mp = MBR_parse_spec(stdin, &disk); bcopy(mbr_binary, mp->code, MBR_CODE_SIZE); MBR_make(mp); } else { /* Use what's on the disk. */ mp = MBR_read_all(&disk); } /* Now do what we are supposed to */ if (i_flag || r_flag || u_flag) { USER_write(&disk, mp, u_flag, y_flag); } if (m_flag) { USER_modify(&disk, mp, 0, 0); } if (mbr_binary) free(mbr_binary); return (0); }