1 | /*␊ |
2 | * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * ␊ |
5 | * This file contains Original Code and/or Modifications of Original Code␊ |
6 | * as defined in and that are subject to the Apple Public Source License␊ |
7 | * Version 2.0 (the 'License'). You may not use this file except in␊ |
8 | * compliance with the License. Please obtain a copy of the License at␊ |
9 | * http://www.opensource.apple.com/apsl/ and read it before using this␊ |
10 | * file.␊ |
11 | * ␊ |
12 | * The Original Code and all software distributed under the License are␊ |
13 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
16 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.␊ |
17 | * Please see the License for the specific language governing rights and␊ |
18 | * limitations under the License.␊ |
19 | * ␊ |
20 | * Copyright (c) 1997 Tobias Weingartner␊ |
21 | * All rights reserved.␊ |
22 | *␊ |
23 | * Redistribution and use in source and binary forms, with or without␊ |
24 | * modification, are permitted provided that the following conditions␊ |
25 | * are met:␊ |
26 | * 1. Redistributions of source code must retain the above copyright␊ |
27 | * notice, this list of conditions and the following disclaimer.␊ |
28 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
29 | * notice, this list of conditions and the following disclaimer in the␊ |
30 | * documentation and/or other materials provided with the distribution.␊ |
31 | * 3. All advertising materials mentioning features or use of this software␊ |
32 | * must display the following acknowledgement:␊ |
33 | * This product includes software developed by Tobias Weingartner.␊ |
34 | * 4. The name of the author may not be used to endorse or promote products␊ |
35 | * derived from this software without specific prior written permission.␊ |
36 | *␊ |
37 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR␊ |
38 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES␊ |
39 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.␊ |
40 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,␊ |
41 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT␊ |
42 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,␊ |
43 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY␊ |
44 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT␊ |
45 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF␊ |
46 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
47 | */␊ |
48 | ␊ |
49 | #include <err.h>␊ |
50 | #include <stdio.h>␊ |
51 | #include <stdlib.h>␊ |
52 | #include <string.h>␊ |
53 | #include <unistd.h>␊ |
54 | #include <paths.h>␊ |
55 | #include <sys/types.h>␊ |
56 | #include <sys/fcntl.h>␊ |
57 | #include "disk.h"␊ |
58 | #include "user.h"␊ |
59 | #include "auto.h"␊ |
60 | ␊ |
61 | #define _PATH_MBR "/usr/standalone/i386/boot0"␊ |
62 | ␊ |
63 | void␊ |
64 | usage()␊ |
65 | {␊ |
66 | ␉extern char * __progname;␊ |
67 | ␉fprintf(stderr, "usage: %s "␊ |
68 | ␉ "[-ieu] [-f mbrboot] [-c cyl -h head -s sect] [-S size] [-r] [-a style] disk\n"␊ |
69 | ␉ "\t-i: initialize disk with new MBR\n"␊ |
70 | ␉ "\t-u: update MBR code, preserve partition table\n"␊ |
71 | ␉ "\t-e: edit MBRs on disk interactively\n"␊ |
72 | ␉ "\t-f: specify non-standard MBR template\n"␊ |
73 | ␉ "\t-chs: specify disk geometry\n"␊ |
74 | ␉ "\t-S: specify disk size\n"␊ |
75 | ␉ "\t-r: read partition specs from stdin (implies -i)\n"␊ |
76 | ␉ "\t-a: auto-partition with the given style\n"␊ |
77 | ␉ "\t-d: dump partition table\n"␊ |
78 | ␉ "\t-y: don't ask any questions\n"␊ |
79 | ␉ "\t-t: test if disk is partitioned\n"␊ |
80 | ␉ "`disk' is of the form /dev/rdisk0.\n",␊ |
81 | ␉ __progname);␊ |
82 | ␉fprintf(stderr, "auto-partition styles:\n");␊ |
83 | ␉AUTO_print_styles(stderr);␊ |
84 | ␉exit(1);␊ |
85 | }␊ |
86 | ␊ |
87 | char *mbr_binary = NULL;␊ |
88 | int␊ |
89 | main(argc, argv)␊ |
90 | ␉int argc;␊ |
91 | ␉char **argv;␊ |
92 | {␊ |
93 | ␉int ch, fd;␊ |
94 | ␉int i_flag = 0, m_flag = 0, u_flag = 0, r_flag = 0, d_flag = 0, y_flag = 0, t_flag = 0;␊ |
95 | ␉int c_arg = 0, h_arg = 0, s_arg = 0;␊ |
96 | ␉int size_arg = 0;␊ |
97 | ␉int block_size_arg = 0;␊ |
98 | ␉disk_t disk;␊ |
99 | ␉DISK_metrics *usermetrics;␊ |
100 | ␉char *mbrfile = _PATH_MBR;␊ |
101 | ␉mbr_t *mp;␊ |
102 | ␉char *auto_style = NULL;␊ |
103 | ␊ |
104 | ␉while ((ch = getopt(argc, argv, "ieuf:c:h:s:b:S:ra:dyt")) != -1) {␊ |
105 | ␉␉switch(ch) {␊ |
106 | ␉␉case 'i':␊ |
107 | ␉␉␉i_flag = 1;␊ |
108 | ␉␉␉break;␊ |
109 | ␉␉case 'u':␊ |
110 | ␉␉␉u_flag = 1;␊ |
111 | ␉␉␉break;␊ |
112 | ␉␉case 'e':␊ |
113 | ␉␉␉m_flag = 1;␊ |
114 | ␉␉␉break;␊ |
115 | ␉␉case 'f':␊ |
116 | ␉␉␉mbrfile = optarg;␊ |
117 | ␉␉␉break;␊ |
118 | ␉␉case 'c':␊ |
119 | ␉␉␉c_arg = atoi(optarg);␊ |
120 | ␉␉␉if (c_arg < 1 || c_arg > 262144)␊ |
121 | ␉␉␉␉errx(1, "Cylinder argument out of range.");␊ |
122 | ␉␉␉break;␊ |
123 | ␉␉case 'h':␊ |
124 | ␉␉␉h_arg = atoi(optarg);␊ |
125 | ␉␉␉if (h_arg < 1 || h_arg > 256)␊ |
126 | ␉␉␉␉errx(1, "Head argument out of range.");␊ |
127 | ␉␉␉break;␊ |
128 | ␉␉case 's':␊ |
129 | ␉␉␉s_arg = atoi(optarg);␊ |
130 | ␉␉␉if (s_arg < 1 || s_arg > 63)␊ |
131 | ␉␉␉␉errx(1, "Sector argument out of range.");␊ |
132 | ␉␉␉break;␊ |
133 | ␉␉case 'b':␊ |
134 | ␉␉␉block_size_arg = atoi(optarg);␊ |
135 | ␉␉␉if (block_size_arg & (block_size_arg - 1))␊ |
136 | ␉␉␉␉errx(1, "Block size argument not a power of two.");␊ |
137 | ␉␉␉if (block_size_arg < 512 || block_size_arg > 4096)␊ |
138 | ␉␉␉␉errx(1, "Block size argument out of range 512..4096.");␊ |
139 | ␉␉␉break;␊ |
140 | ␉␉case 'S':␊ |
141 | ␉␉ size_arg = atoi(optarg);␊ |
142 | ␉␉␉break;␊ |
143 | ␉␉case 'r':␊ |
144 | ␉␉␉r_flag = 1;␊ |
145 | ␉␉␉break;␊ |
146 | ␉␉case 'a':␊ |
147 | ␉␉ auto_style = optarg;␊ |
148 | ␉␉␉break;␊ |
149 | ␉␉case 'd':␊ |
150 | ␉␉ d_flag = 1;␊ |
151 | ␉␉␉break;␊ |
152 | ␉␉case 'y':␊ |
153 | ␉␉ y_flag = 1;␊ |
154 | ␉␉␉break;␊ |
155 | ␉␉case 't':␊ |
156 | ␉␉ t_flag = 1;␊ |
157 | ␉␉␉break;␊ |
158 | ␉␉default:␊ |
159 | ␉␉␉usage();␊ |
160 | ␉␉}␊ |
161 | ␉}␊ |
162 | ␉argc -= optind;␊ |
163 | ␉argv += optind;␊ |
164 | ␊ |
165 | ␉/* Argument checking */␊ |
166 | ␉if (argc != 1)␊ |
167 | ␉␉usage();␊ |
168 | ␉else␊ |
169 | ␉␉disk.name = argv[0];␊ |
170 | ␊ |
171 | ␉if (i_flag && u_flag) errx(1, "-i and -u cannot be specified simultaneously");␊ |
172 | ␊ |
173 | ␉/* Put in supplied geometry if there */␊ |
174 | ␉if (c_arg | h_arg | s_arg | size_arg | block_size_arg) {␊ |
175 | ␉␉usermetrics = malloc(sizeof(DISK_metrics));␊ |
176 | ␉␉if (usermetrics != NULL) {␊ |
177 | ␉␉␉if (c_arg && h_arg && s_arg) {␊ |
178 | ␉␉␉␉usermetrics->cylinders = c_arg;␊ |
179 | ␉␉␉␉usermetrics->heads = h_arg;␊ |
180 | ␉␉␉␉usermetrics->sectors = s_arg;␊ |
181 | ␉␉␉␉if (size_arg) {␊ |
182 | ␉␉␉␉ usermetrics->size = size_arg;␊ |
183 | ␉␉␉␉} else {␊ |
184 | ␉␉␉␉ usermetrics->size = c_arg * h_arg * s_arg;␊ |
185 | ␉␉␉␉}␊ |
186 | ␉␉␉} else {␊ |
187 | ␉␉␉ if (size_arg) {␊ |
188 | ␉␉␉ usermetrics->size = size_arg;␊ |
189 | ␉␉␉ DISK_fake_CHS(usermetrics);␊ |
190 | ␉␉␉ } else {␊ |
191 | ␉␉␉ errx(1, "Please specify a full geometry with [-chs].");␊ |
192 | ␉␉␉ }␊ |
193 | ␉␉␉}␊ |
194 | ␉␉␉if (block_size_arg) {␊ |
195 | ␉␉␉␉usermetrics->sector_size = block_size_arg;␊ |
196 | ␉␉␉} else {␊ |
197 | ␉␉␉␉DISK_get_sector_size(&disk, usermetrics);␊ |
198 | ␉␉␉}␊ |
199 | ␉␉}␊ |
200 | ␉} else {␊ |
201 | ␉␉usermetrics = NULL;␊ |
202 | ␉}␊ |
203 | ␊ |
204 | ␉/* Get the geometry */␊ |
205 | ␉disk.real = NULL;␊ |
206 | ␉if (DISK_getmetrics(&disk, usermetrics))␊ |
207 | ␉␉errx(1, "Can't get disk geometry, please use [-chs] to specify.");␊ |
208 | ␊ |
209 | ␉/* If only testing, read MBR and silently exit */␊ |
210 | ␉if (t_flag) {␊ |
211 | ␉ mbr_t *mbr;␊ |
212 | ␊ |
213 | ␉ mp = mbr = MBR_read_all(&disk);␊ |
214 | ␉ while (mp) {␊ |
215 | ␉ if (mp->signature != MBR_SIGNATURE) {␊ |
216 | ␉ MBR_free(mbr);␊ |
217 | ␉ exit(1);␊ |
218 | ␉ }␊ |
219 | ␉ mp = mp->next;␊ |
220 | ␉ }␊ |
221 | ␉ MBR_free(mbr);␊ |
222 | ␉ exit(0);␊ |
223 | ␉}␊ |
224 | ␊ |
225 | ␉/* If not editing the disk, print out current MBRs on disk */␊ |
226 | ␉if ((i_flag + r_flag + u_flag + m_flag) == 0) {␊ |
227 | ␉␉exit(USER_print_disk(&disk, d_flag));␊ |
228 | ␉}␊ |
229 | ␊ |
230 | ␉/* Parse mbr template or read partition specs, to pass on later */␊ |
231 | ␉if (auto_style && r_flag) {␊ |
232 | ␉ errx(1, "Can't specify both -r and -a");␊ |
233 | ␉}␊ |
234 | ␊ |
235 | ␉mbr_binary = (char *)malloc(MBR_CODE_SIZE);␊ |
236 | ␉if ((fd = open(mbrfile, O_RDONLY)) == -1) {␊ |
237 | ␉ warn("could not open MBR file %s", mbrfile);␊ |
238 | ␉ bzero(mbr_binary, MBR_CODE_SIZE);␊ |
239 | ␉} else {␊ |
240 | ␉ int cc;␊ |
241 | ␉ cc = read(fd, mbr_binary, MBR_CODE_SIZE);␊ |
242 | ␉ if (cc < MBR_CODE_SIZE) {␊ |
243 | ␉ err(1, "could not read MBR code");␊ |
244 | ␉ }␊ |
245 | ␉ close(fd);␊ |
246 | ␉}␊ |
247 | ␊ |
248 | ␉if (u_flag) {␊ |
249 | ␉ /* Don't hose the partition table; just write the boot code */␊ |
250 | ␉ mp = MBR_read_all(&disk);␊ |
251 | ␉ bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);␊ |
252 | ␉ MBR_make(mp);␊ |
253 | ␉} else if (i_flag) {␊ |
254 | ␉ /* If they didn't specify -a, they'll get the default auto style */␊ |
255 | ␉ mp = MBR_alloc(NULL);␊ |
256 | ␉ if (AUTO_init(&disk, auto_style, mp) != AUTO_OK) {␊ |
257 | ␉ errx(1, "error initializing disk");␊ |
258 | ␉ }␊ |
259 | ␉ bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);␊ |
260 | ␉ MBR_make(mp);␊ |
261 | ␉} else if (r_flag) {␊ |
262 | ␉ mp = MBR_parse_spec(stdin, &disk);␊ |
263 | ␉ bcopy(mbr_binary, mp->code, MBR_CODE_SIZE);␊ |
264 | ␉ MBR_make(mp);␊ |
265 | ␉} else {␊ |
266 | ␉ /* Use what's on the disk. */␊ |
267 | ␉ mp = MBR_read_all(&disk);␊ |
268 | ␉}␊ |
269 | ␉ ␊ |
270 | ␉/* Now do what we are supposed to */␊ |
271 | ␉if (i_flag || r_flag || u_flag) {␊ |
272 | ␉ USER_write(&disk, mp, u_flag, y_flag);␊ |
273 | ␉}␊ |
274 | ␊ |
275 | ␉if (m_flag) {␊ |
276 | ␉ USER_modify(&disk, mp, 0, 0);␊ |
277 | ␉}␊ |
278 | ␊ |
279 | ␉if (mbr_binary)␊ |
280 | ␉ free(mbr_binary);␊ |
281 | ␊ |
282 | ␉return (0);␊ |
283 | }␊ |
284 | |