]>
git.cameronkatri.com Git - apple_cmds.git/blob - diskdev_cmds/fdisk.tproj/mbr.c
2 * Copyright (c) 2002, 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1997 Tobias Weingartner
26 * All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
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.
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.
61 #include <sys/fcntl.h>
62 #include <sys/ioctl.h>
63 #include <sys/types.h>
68 #include <machine/param.h>
80 /* Fix up given mbr for this disk */
81 mbr
->part
[0].flag
= 0;
82 mbr
->part
[1].flag
= 0;
83 mbr
->part
[2].flag
= 0;
84 #if !defined(DOSPTYP_OPENBSD)
85 mbr
->part
[3].flag
= 0;
86 mbr
->signature
= MBR_SIGNATURE
;
89 mbr
->part
[3].flag
= DOSACTIVE
;
90 mbr
->signature
= DOSMBR_SIGNATURE
;
92 /* Use whole disk, save for first head, on first cyl. */
93 mbr
->part
[3].id
= DOSPTYP_OPENBSD
;
94 mbr
->part
[3].scyl
= 0;
95 mbr
->part
[3].shead
= 1;
96 mbr
->part
[3].ssect
= 1;
98 /* Go right to the end */
99 mbr
->part
[3].ecyl
= disk
->real
->cylinders
- 1;
100 mbr
->part
[3].ehead
= disk
->real
->heads
- 1;
101 mbr
->part
[3].esect
= disk
->real
->sectors
;
103 /* Fix up start/length fields */
104 PRT_fix_BN(disk
, &mbr
->part
[3], 3);
106 #if defined(__powerpc__) || defined(__mips__)
107 /* Now fix up for the MS-DOS boot partition on PowerPC. */
108 mbr
->part
[0].flag
= DOSACTIVE
; /* Boot from dos part */
109 mbr
->part
[3].flag
= 0;
110 mbr
->part
[3].ns
+= mbr
->part
[3].bs
;
111 mbr
->part
[3].bs
= mbr
->part
[0].bs
+ mbr
->part
[0].ns
;
112 mbr
->part
[3].ns
-= mbr
->part
[3].bs
;
113 PRT_fix_CHS(disk
, &mbr
->part
[3], 3);
114 if ((mbr
->part
[3].shead
!= 1) || (mbr
->part
[3].ssect
!= 1)) {
115 /* align the partition on a cylinder boundary */
116 mbr
->part
[3].shead
= 0;
117 mbr
->part
[3].ssect
= 1;
118 mbr
->part
[3].scyl
+= 1;
120 /* Fix up start/length fields */
121 PRT_fix_BN(disk
, &mbr
->part
[3], 3);
127 MBR_parse(disk
, offset
, reloff
, mbr
)
134 unsigned char *mbr_buf
= mbr
->buf
;
136 memcpy(mbr
->code
, mbr_buf
, MBR_CODE_SIZE
);
137 mbr
->offset
= offset
;
138 mbr
->reloffset
= reloff
;
139 mbr
->signature
= getshort(&mbr_buf
[MBR_SIG_OFF
]);
141 for (i
= 0; i
< NDOSPART
; i
++)
142 PRT_parse(disk
, &mbr_buf
[MBR_PART_OFF
+ MBR_PART_SIZE
* i
],
143 offset
, reloff
, &mbr
->part
[i
], i
);
151 unsigned char *mbr_buf
= mbr
->buf
;
153 memcpy(mbr_buf
, mbr
->code
, MBR_CODE_SIZE
);
154 putshort(&mbr_buf
[MBR_SIG_OFF
], mbr
->signature
);
156 for (i
= 0; i
< NDOSPART
; i
++)
157 PRT_make(&mbr
->part
[i
], mbr
->offset
, mbr
->reloffset
,
158 &mbr_buf
[MBR_PART_OFF
+ MBR_PART_SIZE
* i
]);
168 printf("Signature: 0x%X\n",
169 (int)mbr
->signature
);
173 for (i
= 0; i
< NDOSPART
; i
++)
174 PRT_print(i
, &mbr
->part
[i
]);
178 MBR_read(disk
, fd
, where
, mbr
)
187 unsigned char *buf
= mbr
->buf
;
189 size
= disk
->real
->sector_size
;
191 off
= lseek(fd
, where
, SEEK_SET
);
194 len
= read(fd
, buf
, size
);
201 MBR_write(disk
, fd
, mbr
)
209 unsigned char *buf
= mbr
->buf
;
212 size
= disk
->real
->sector_size
;
213 where
= mbr
->offset
* size
;
214 off
= lseek(fd
, where
, SEEK_SET
);
217 len
= write(fd
, buf
, size
);
220 #if defined(DIOCRLDINFO)
221 (void) ioctl(fd
, DIOCRLDINFO
, 0);
232 * Copy partition table from the disk indicated
233 * to the supplied mbr structure
236 int i
, fd
, offset
= 0, reloff
= 0;
239 mbrd
= MBR_alloc(NULL
);
240 fd
= DISK_open(disk
->name
, O_RDONLY
);
241 MBR_read(disk
, fd
, offset
, mbrd
);
243 MBR_parse(disk
, offset
, reloff
, mbrd
);
244 for (i
= 0; i
< NDOSPART
; i
++) {
245 PRT_parse(disk
, &mbrd
->buf
[MBR_PART_OFF
+
247 offset
, reloff
, &mbr
->part
[i
], i
);
248 PRT_print(i
, &mbr
->part
[i
]);
255 parse_number(char *str
, int default_val
, int base
) {
256 if (str
!= NULL
&& *str
!= '\0') {
257 default_val
= strtol(str
, NULL
, base
);
263 null_arg(char *arg
) {
264 if (arg
== NULL
|| *arg
== 0)
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."
279 MBR_parse_one_spec(char *line
, disk_t
*disk
, mbr_t
*mbr
, int pn
)
283 prt_t
*part
= &mbr
->part
[pn
];
284 int next_start
, next_size
;
286 /* There are up to 10 arguments. */
287 for (i
=0; i
<N_ARGS
; i
++) {
289 while (isspace(*line
))
291 arg
= strsep(&line
, ",\n");
292 if (arg
== NULL
|| line
== NULL
) {
297 for (; i
<N_ARGS
; i
++) {
300 /* Set reasonable defaults. */
304 next_start
= mbr
->part
[pn
-1].bs
+ mbr
->part
[pn
-1].ns
;
306 next_size
= disk
->real
->size
;
307 for(i
=0; i
<pn
; i
++) {
308 next_size
-= mbr
->part
[i
].ns
;
311 part
->id
= parse_number(args
[2], 0xA8, 16);
312 if (!null_arg(args
[3]) && *args
[3] == '*') {
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");
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
])) {
330 errx(1, "Either all CHS arguments must be specified, or none");
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
);
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");
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
);
360 typedef struct _mbr_chain
{
362 struct _mbr_chain
*next
;
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>]
371 MBR_parse_spec(FILE *f
, disk_t
*disk
)
374 int offset
, firstoffset
;
375 mbr_t
*mbr
, *head
, *prev_mbr
;
377 head
= mbr
= prev_mbr
= NULL
;
382 for (lineno
= 0; lineno
< NDOSPART
&& !feof(f
); lineno
++) {
388 str
= fgets(line
, 256, f
);
389 } while ((str
!= NULL
) && (*str
== '\0'));
395 mbr
= MBR_alloc(prev_mbr
);
400 if (MBR_parse_one_spec(line
, disk
, mbr
, lineno
)) {
401 /* MBR_parse_one_spec printed the error message. */
404 part
= &mbr
->part
[lineno
];
405 if ((part
->id
== DOSPTYP_EXTEND
) || (part
->id
== DOSPTYP_EXTENDL
)) {
407 if (firstoffset
== 0) firstoffset
= offset
;
410 /* If fewer lines than partitions, zero out the rest of the partitions */
412 for (; lineno
< NDOSPART
; lineno
++) {
413 bzero(&mbr
->part
[lineno
], sizeof(prt_t
));
418 } while (offset
>= 0 && !feof(f
));
429 for (i
=0; i
<NDOSPART
; i
++) {
430 part
= &mbr
->part
[i
];
431 printf("%d,%d,0x%02X,%c,%u,%u,%u,%u,%u,%u\n",
435 (part
->flag
== 0x80) ? '*' : '-',
446 MBR_alloc(mbr_t
*parent
)
448 mbr_t
*mbr
= (mbr_t
*)malloc(sizeof(mbr_t
));
449 bzero(mbr
, sizeof(mbr_t
));
453 mbr
->signature
= MBR_SIGNATURE
;
468 /* Read and parse all the partition tables on the disk,
469 * including extended partitions.
472 MBR_read_all(disk_t
*disk
)
474 mbr_t
*mbr
= NULL
, *head
= NULL
;
475 int i
, fd
, offset
, firstoff
;
477 fd
= DISK_open(disk
->name
, O_RDONLY
);
478 firstoff
= offset
= 0;
480 mbr
= MBR_alloc(mbr
);
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. */
491 for (i
=0; i
<NDOSPART
; i
++) {
492 prt_t
*part
= &mbr
->part
[i
];
493 if ((part
->id
== DOSPTYP_EXTEND
) || (part
->id
== DOSPTYP_EXTENDL
)) {
500 } while (offset
> 0);
508 MBR_write_all(disk_t
*disk
, mbr_t
*mbr
)
513 fd
= DISK_open(disk
->name
, O_RDWR
);
516 result
= MBR_write(disk
, fd
, mbr
);
526 MBR_print_all(mbr_t
*mbr
) {
534 MBR_dump_all(mbr_t
*mbr
) {
542 MBR_clear(mbr_t
*mbr
) {
548 for (i
=0; i
<4; i
++) {
549 bzero(&mbr
->part
[i
], sizeof(mbr
->part
[i
]));
551 bzero(&mbr
->buf
, sizeof(mbr
->buf
));