Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/util/fdisk/mbr.c

Source at commit 1808 created 12 years 4 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
1/*
2 * Copyright (c) 2002, 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * Copyright (c) 1997 Tobias Weingartner
26 * All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by Tobias Weingartner.
39 * 4. The name of the author may not be used to endorse or promote products
40 * derived from this software without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 */
53
54#include <err.h>
55#include <util.h>
56#include <stdio.h>
57#include <unistd.h>
58#include <stdlib.h>
59#include <ctype.h>
60#include <memory.h>
61#include <sys/fcntl.h>
62#include <sys/ioctl.h>
63#include <sys/types.h>
64#include <sys/stat.h>
65#if 0
66#include <sys/dkio.h>
67#endif
68#include <machine/param.h>
69#include "disk.h"
70#include "misc.h"
71#include "mbr.h"
72#include "part.h"
73
74
75void
76MBR_init(disk, mbr)
77disk_t *disk;
78mbr_t *mbr;
79{
80/* Fix up given mbr for this disk */
81mbr->part[0].flag = 0;
82mbr->part[1].flag = 0;
83mbr->part[2].flag = 0;
84#if !defined(DOSPTYP_OPENBSD)
85mbr->part[3].flag = 0;
86mbr->signature = MBR_SIGNATURE;
87#else
88
89mbr->part[3].flag = DOSACTIVE;
90mbr->signature = DOSMBR_SIGNATURE;
91
92/* Use whole disk, save for first head, on first cyl. */
93mbr->part[3].id = DOSPTYP_OPENBSD;
94mbr->part[3].scyl = 0;
95mbr->part[3].shead = 1;
96mbr->part[3].ssect = 1;
97
98/* Go right to the end */
99mbr->part[3].ecyl = disk->real->cylinders - 1;
100mbr->part[3].ehead = disk->real->heads - 1;
101mbr->part[3].esect = disk->real->sectors;
102
103/* Fix up start/length fields */
104PRT_fix_BN(disk, &mbr->part[3], 3);
105
106#if defined(__powerpc__) || defined(__mips__)
107/* Now fix up for the MS-DOS boot partition on PowerPC. */
108mbr->part[0].flag = DOSACTIVE;/* Boot from dos part */
109mbr->part[3].flag = 0;
110mbr->part[3].ns += mbr->part[3].bs;
111mbr->part[3].bs = mbr->part[0].bs + mbr->part[0].ns;
112mbr->part[3].ns -= mbr->part[3].bs;
113PRT_fix_CHS(disk, &mbr->part[3], 3);
114if ((mbr->part[3].shead != 1) || (mbr->part[3].ssect != 1)) {
115/* align the partition on a cylinder boundary */
116mbr->part[3].shead = 0;
117mbr->part[3].ssect = 1;
118mbr->part[3].scyl += 1;
119}
120/* Fix up start/length fields */
121PRT_fix_BN(disk, &mbr->part[3], 3);
122#endif
123#endif
124}
125
126void
127MBR_parse(disk, offset, reloff, mbr)
128disk_t *disk;
129off_t offset;
130off_t reloff;
131mbr_t *mbr;
132{
133int i;
134unsigned char *mbr_buf = mbr->buf;
135
136memcpy(mbr->code, mbr_buf, MBR_CODE_SIZE);
137mbr->offset = offset;
138mbr->reloffset = reloff;
139mbr->signature = getshort(&mbr_buf[MBR_SIG_OFF]);
140
141for (i = 0; i < NDOSPART; i++)
142PRT_parse(disk, &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i],
143 offset, reloff, &mbr->part[i], i);
144}
145
146void
147MBR_make(mbr)
148mbr_t *mbr;
149{
150int i;
151unsigned char *mbr_buf = mbr->buf;
152
153memcpy(mbr_buf, mbr->code, MBR_CODE_SIZE);
154putshort(&mbr_buf[MBR_SIG_OFF], mbr->signature);
155
156for (i = 0; i < NDOSPART; i++)
157PRT_make(&mbr->part[i], mbr->offset, mbr->reloffset,
158 &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i]);
159}
160
161void
162MBR_print(mbr)
163mbr_t *mbr;
164{
165int i;
166
167/* Header */
168printf("Signature: 0x%X\n",
169 (int)mbr->signature);
170PRT_print(0, NULL);
171
172/* Entries */
173for (i = 0; i < NDOSPART; i++)
174PRT_print(i, &mbr->part[i]);
175}
176
177int
178MBR_read(disk, fd, where, mbr)
179disk_t *disk;
180int fd;
181off_t where;
182mbr_t *mbr;
183{
184off_t off;
185int len;
186int size;
187unsigned char *buf = mbr->buf;
188
189size = disk->real->sector_size;
190where *= size;
191off = lseek(fd, where, SEEK_SET);
192if (off != where)
193return (off);
194len = read(fd, buf, size);
195if (len != size)
196return (len);
197return (0);
198}
199
200int
201MBR_write(disk, fd, mbr)
202disk_t *disk;
203int fd;
204mbr_t *mbr;
205{
206off_t off;
207int len;
208int size;
209unsigned char *buf = mbr->buf;
210off_t where;
211
212size = disk->real->sector_size;
213where = mbr->offset * size;
214off = lseek(fd, where, SEEK_SET);
215if (off != where)
216return (off);
217len = write(fd, buf, size);
218if (len != size)
219return (len);
220#if defined(DIOCRLDINFO)
221(void) ioctl(fd, DIOCRLDINFO, 0);
222#endif
223return (0);
224}
225
226void
227MBR_pcopy(disk, mbr)
228disk_t *disk;
229mbr_t *mbr;
230{
231/*
232 * Copy partition table from the disk indicated
233 * to the supplied mbr structure
234 */
235
236int i, fd, offset = 0, reloff = 0;
237mbr_t *mbrd;
238
239mbrd = MBR_alloc(NULL);
240fd = DISK_open(disk->name, O_RDONLY);
241MBR_read(disk, fd, offset, mbrd);
242DISK_close(fd);
243MBR_parse(disk, offset, reloff, mbrd);
244for (i = 0; i < NDOSPART; i++) {
245PRT_parse(disk, &mbrd->buf[MBR_PART_OFF +
246 MBR_PART_SIZE * i],
247 offset, reloff, &mbr->part[i], i);
248PRT_print(i, &mbr->part[i]);
249}
250MBR_free(mbrd);
251}
252
253
254static int
255parse_number(char *str, int default_val, int base) {
256if (str != NULL && *str != '\0') {
257 default_val = strtol(str, NULL, base);
258}
259return default_val;
260}
261
262static inline int
263null_arg(char *arg) {
264 if (arg == NULL || *arg == 0)
265 return 1;
266 else
267 return 0;
268}
269
270/* Parse a partition spec into a partition structure.
271 * Spec is of the form:
272 * <start>,<size>,<id>,<bootable>[,<c,h,s>,<c,h,s>]
273 * We require passing in the disk and mbr so we can
274 * set reasonable defaults for values, e.g. "the whole disk"
275 * or "starting after the last partition."
276 */
277#define N_ARGS 10
278static int
279MBR_parse_one_spec(char *line, disk_t *disk, mbr_t *mbr, int pn)
280{
281 int i;
282 char *args[N_ARGS];
283 prt_t *part = &mbr->part[pn];
284 int next_start, next_size;
285
286 /* There are up to 10 arguments. */
287 for (i=0; i<N_ARGS; i++) {
288 char *arg;
289 while (isspace(*line))
290 line++;
291 arg = strsep(&line, ",\n");
292 if (arg == NULL || line == NULL) {
293 break;
294 }
295 args[i] = arg;
296 }
297 for (; i<N_ARGS; i++) {
298 args[i] = NULL;
299 }
300 /* Set reasonable defaults. */
301 if (pn == 0) {
302 next_start = 0;
303 } else {
304 next_start = mbr->part[pn-1].bs + mbr->part[pn-1].ns;
305 }
306 next_size = disk->real->size;
307 for(i=0; i<pn; i++) {
308 next_size -= mbr->part[i].ns;
309 }
310
311 part->id = parse_number(args[2], 0xA8, 16);
312 if (!null_arg(args[3]) && *args[3] == '*') {
313 part->flag = 0x80;
314 } else {
315 part->flag = 0;
316 }
317 /* If you specify the start or end sector,
318 you have to give both. */
319 if ((null_arg(args[0]) && !null_arg(args[1])) ||
320 (!null_arg(args[0]) && null_arg(args[1]))) {
321 errx(1, "You must specify both start and size, or neither");
322 return -1;
323 }
324
325 /* If you specify one of the CHS args,
326 you have to give them all. */
327 if (!null_arg(args[4])) {
328 for (i=5; i<10; i++) {
329 if (null_arg(args[i])) {
330errx(1, "Either all CHS arguments must be specified, or none");
331return -1;
332 }
333 }
334
335 part->scyl = parse_number(args[4], 0, 10);
336 part->shead = parse_number(args[5], 0, 10);
337 part->ssect = parse_number(args[6], 0, 10);
338 part->scyl = parse_number(args[7], 0, 10);
339 part->shead = parse_number(args[8], 0, 10);
340 part->ssect = parse_number(args[9], 0, 10);
341 if (null_arg(args[0])) {
342 PRT_fix_BN(disk, part, pn);
343 }
344 } else {
345 /* See if they gave no CHS and no start/end */
346 if (null_arg(args[0])) {
347 errx(1, "You must specify either start sector and size or CHS");
348 return -1;
349 }
350 }
351 if (!null_arg(args[0])) {
352 part->bs = parse_number(args[0], next_start, 10);
353 part->ns = parse_number(args[1], next_size, 10);
354 PRT_fix_CHS(disk, part, pn);
355 }
356 return 0;
357}
358
359
360typedef struct _mbr_chain {
361 mbr_t mbr;
362 struct _mbr_chain *next;
363} mbr_chain_t;
364
365/* Parse some number of MBR spec lines.
366 * Spec is of the form:
367 * <start>,<size>,<id>,<bootable>[,<c,h,s>,<c,h,s>]
368 *
369 */
370mbr_t *
371MBR_parse_spec(FILE *f, disk_t *disk)
372{
373 int lineno;
374 int offset, firstoffset;
375 mbr_t *mbr, *head, *prev_mbr;
376
377 head = mbr = prev_mbr = NULL;
378 firstoffset = 0;
379 do {
380
381 offset = 0;
382 for (lineno = 0; lineno < NDOSPART && !feof(f); lineno++) {
383 char line[256];
384 char *str;
385prt_t *part;
386
387do {
388 str = fgets(line, 256, f);
389} while ((str != NULL) && (*str == '\0'));
390 if (str == NULL) {
391 break;
392 }
393
394if (mbr == NULL) {
395 mbr = MBR_alloc(prev_mbr);
396 if (head == NULL)
397head = mbr;
398}
399
400if (MBR_parse_one_spec(line, disk, mbr, lineno)) {
401 /* MBR_parse_one_spec printed the error message. */
402 return NULL;
403}
404part = &mbr->part[lineno];
405if ((part->id == DOSPTYP_EXTEND) || (part->id == DOSPTYP_EXTENDL)) {
406 offset = part->bs;
407 if (firstoffset == 0) firstoffset = offset;
408}
409 }
410 /* If fewer lines than partitions, zero out the rest of the partitions */
411 if (mbr != NULL) {
412for (; lineno < NDOSPART; lineno++) {
413 bzero(&mbr->part[lineno], sizeof(prt_t));
414}
415 }
416 prev_mbr = mbr;
417 mbr = NULL;
418 } while (offset >= 0 && !feof(f));
419
420 return head;
421}
422
423void
424MBR_dump(mbr_t *mbr)
425{
426 int i;
427 prt_t *part;
428
429 for (i=0; i<NDOSPART; i++) {
430 part = &mbr->part[i];
431 printf("%d,%d,0x%02X,%c,%d,%d,%d,%d,%d,%d\n",
432 part->bs,
433 part->ns,
434 part->id,
435 (part->flag == 0x80) ? '*' : '-',
436 part->scyl,
437 part->shead,
438 part->ssect,
439 part->ecyl,
440 part->ehead,
441 part->esect);
442 }
443}
444
445mbr_t *
446MBR_alloc(mbr_t *parent)
447{
448 mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
449 bzero(mbr, sizeof(mbr_t));
450 if (parent) {
451 parent->next = mbr;
452 }
453 mbr->signature = MBR_SIGNATURE;
454 return mbr;
455}
456
457void
458MBR_free(mbr_t *mbr)
459{
460 mbr_t *tmp;
461 while (mbr) {
462 tmp = mbr->next;
463 free(mbr);
464 mbr = tmp;
465 }
466}
467
468/* Read and parse all the partition tables on the disk,
469 * including extended partitions.
470 */
471mbr_t *
472MBR_read_all(disk_t *disk)
473{
474 mbr_t *mbr = NULL, *head = NULL;
475 int i, fd, offset, firstoff;
476
477 fd = DISK_open(disk->name, O_RDONLY);
478 firstoff = offset = 0;
479 do {
480 mbr = MBR_alloc(mbr);
481 if (head == NULL) {
482 head = mbr;
483 }
484 MBR_read(disk, fd, offset, mbr);
485 MBR_parse(disk, offset, firstoff, mbr);
486 if (mbr->signature != MBR_SIGNATURE) {
487 /* The MBR signature is invalid. */
488 break;
489 }
490 offset = 0;
491 for (i=0; i<NDOSPART; i++) {
492 prt_t *part = &mbr->part[i];
493 if ((part->id == DOSPTYP_EXTEND) || (part->id == DOSPTYP_EXTENDL)) {
494offset = part->bs;
495if (firstoff == 0) {
496 firstoff = offset;
497}
498 }
499 }
500 } while (offset > 0);
501 DISK_close(fd);
502
503 return head;
504}
505
506
507int
508MBR_write_all(disk_t *disk, mbr_t *mbr)
509{
510 int result = 0;
511 int fd;
512
513 fd = DISK_open(disk->name, O_RDWR);
514 while (mbr) {
515 MBR_make(mbr);
516 result = MBR_write(disk, fd, mbr);
517 if (result)
518 break;
519 mbr = mbr->next;
520 }
521 DISK_close(fd);
522 return result;
523}
524
525void
526MBR_print_all(mbr_t *mbr) {
527 while (mbr) {
528 MBR_print(mbr);
529 mbr = mbr->next;
530 }
531}
532
533void
534MBR_dump_all(mbr_t *mbr) {
535 while (mbr) {
536 MBR_dump(mbr);
537 mbr = mbr->next;
538 }
539}
540
541void
542MBR_clear(mbr_t *mbr) {
543 int i;
544 if (mbr->next) {
545 MBR_free(mbr->next);
546 mbr->next = NULL;
547 }
548 for (i=0; i<4; i++) {
549 bzero(&mbr->part[i], sizeof(mbr->part[i]));
550 }
551 bzero(&mbr->buf, sizeof(mbr->buf));
552}
553
554

Archive Download this file

Revision: 1808