4 * Copyright (C) 1998 Wolfgang Solfrank.
5 * Copyright (C) 1998 TooLs GmbH.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: mbrlabel.c,v 1.26 2005/12/28 06:03:15 christos Exp $");
49 #include <sys/param.h>
51 #include <sys/disklabel.h>
52 #include <sys/bootblock.h>
53 #include <sys/ioctl.h>
58 int main(int, char **);
61 void setlabel(int, int);
62 int getparts(int, int);
63 struct apple_drvr_map
*convert_drvr_map(unsigned char *);
64 struct apple_part_map_entry
*convert_part_map_entry(unsigned char *);
66 struct disklabel label
;
72 if (ioctl(sd
, DIOCGDINFO
, &label
) < 0) {
77 * Some ports seem to not set the number of partitions
78 * correctly, albeit they seem to set the raw partition ok!
80 if (label
.d_npartitions
<= getrawpartition())
81 label
.d_npartitions
= getrawpartition() + 1;
85 setlabel(int sd
, int doraw
)
90 label
.d_checksum
= dkcksum(&label
);
91 if (ioctl(sd
, doraw
? DIOCWDINFO
: DIOCSDINFO
, &label
) < 0) {
96 /* If we haven't written to the disk, don't discard on close */
97 ioctl(sd
, DIOCKLABEL
, &one
);
102 getparts(int sd
, int verbose
)
104 unsigned char buf
[DEV_BSIZE
];
105 struct apple_drvr_map
*drvr
;
106 struct apple_part_map_entry
*part
;
107 struct partition npe
;
108 uint16_t blksize
, blkcnt
, partcnt
;
109 int i
, j
, unused
, changed
;
114 if (lseek(sd
, 0, SEEK_SET
) == -1) {
115 perror("seek drvr map");
118 if ((i
=read(sd
, buf
, sizeof(buf
))) != DEV_BSIZE
) {
119 perror("read drvr map");
122 drvr
= convert_drvr_map(buf
);
124 if (drvr
->sbSig
!= APPLE_DRVR_MAP_MAGIC
)
126 blksize
= drvr
->sbBlockSize
;
127 blkcnt
= drvr
->sbBlkCount
;
131 for (i
= 0; i
< partcnt
; i
++) {
132 if (lseek(sd
, (i
+1)*blksize
, SEEK_SET
) == -1) {
136 if (read(sd
, buf
, sizeof(buf
)) != DEV_BSIZE
) {
141 part
= convert_part_map_entry(buf
);
143 if (part
->pmSig
!= APPLE_PART_MAP_ENTRY_MAGIC
)
146 partcnt
= part
->pmMapBlkCnt
;
147 /* XXX: consistency checks? */
149 memset((void *)&npe
, 0, sizeof(npe
));
151 if (strcasecmp((char *)part
->pmPartType
,
152 APPLE_PART_TYPE_MAC
) == 0
153 || strcasecmp((char *)part
->pmPartType
, "Apple_HFSX") == 0)
154 npe
.p_fstype
= FS_HFS
;
155 else if (strcasecmp((char *)part
->pmPartType
,
157 npe
.p_fstype
= FS_APPLEUFS
;
158 npe
.p_size
= 16384; /* XXX */
166 temp
= (uint64_t)part
->pmDataCnt
* (uint64_t)blksize
;
167 if (temp
% label
.d_secsize
!= 0) {
168 warnx("partition size not multiple of sector size"
172 npe
.p_size
= temp
/ label
.d_secsize
;
173 temp
= (uint64_t)(part
->pmPyPartStart
+ part
->pmLgDataStart
)
175 if (temp
% label
.d_secsize
!= 0) {
176 warnx("partition offset not multiple of sector size"
180 npe
.p_offset
= temp
/ label
.d_secsize
;
182 /* find existing entry, or first free slot */
183 unused
= -1; /* flag as no free slot */
186 "Found %s partition; size %u (%u MB), offset %u\n",
187 fstypenames
[npe
.p_fstype
],
188 npe
.p_size
, npe
.p_size
/ 2048, npe
.p_offset
);
189 for (j
= 0; j
< label
.d_npartitions
; j
++) {
190 struct partition
*lpe
;
194 lpe
= &label
.d_partitions
[j
];
195 if (lpe
->p_size
== npe
.p_size
&&
196 lpe
->p_offset
== npe
.p_offset
198 && (lpe
->p_fstype
== npe
.p_fstype
||
199 lpe
->p_fstype
== FS_UNUSED
) */
204 " skipping existing %s partition at slot %c.\n",
205 fstypenames
[lpe
->p_fstype
],
207 unused
= -2; /* flag as existing */
210 if (unused
== -1 && lpe
->p_size
== 0 &&
211 lpe
->p_fstype
== FS_UNUSED
)
215 continue; /* entry exists, skip... */
217 if (label
.d_npartitions
< MAXPARTITIONS
) {
218 unused
= label
.d_npartitions
;
219 label
.d_npartitions
++;
222 " WARNING: no slots free for %s partition.\n",
223 fstypenames
[npe
.p_fstype
]);
229 printf(" adding %s partition to slot %c.\n",
230 fstypenames
[npe
.p_fstype
], unused
+ 'a');
232 label
.d_partitions
[unused
] = npe
;
238 struct apple_drvr_map
*
239 convert_drvr_map(unsigned char *buf
)
241 struct apple_drvr_map
*drvr
;
244 drvr
= (struct apple_drvr_map
*)buf
;
246 BE16TOH(drvr
->sbSig
);
247 BE16TOH(drvr
->sbBlockSize
);
248 BE32TOH(drvr
->sbBlkCount
);
249 BE16TOH(drvr
->sbDevType
);
250 BE16TOH(drvr
->sbDevID
);
251 BE32TOH(drvr
->sbData
);
252 BE16TOH(drvr
->sbDrvrCount
);
253 for (i
=0; i
<APPLE_DRVR_MAP_MAX_DESCRIPTORS
; i
++) {
254 BE32TOH(drvr
->sb_dd
[i
].descBlock
);
255 BE16TOH(drvr
->sb_dd
[i
].descSize
);
256 BE16TOH(drvr
->sb_dd
[i
].descType
);
262 struct apple_part_map_entry
*
263 convert_part_map_entry(unsigned char *buf
)
265 struct apple_part_map_entry
*part
;
267 part
= (struct apple_part_map_entry
*)buf
;
269 BE16TOH(part
->pmSig
);
270 BE16TOH(part
->pmSigPad
);
271 BE32TOH(part
->pmMapBlkCnt
);
272 BE32TOH(part
->pmPyPartStart
);
273 BE32TOH(part
->pmPartBlkCnt
);
274 BE32TOH(part
->pmLgDataStart
);
275 BE32TOH(part
->pmDataCnt
);
276 BE32TOH(part
->pmPartStatus
);
277 BE32TOH(part
->pmLgBootStart
);
278 BE32TOH(part
->pmBootSize
);
279 BE32TOH(part
->pmBootLoad
);
280 BE32TOH(part
->pmBootLoad2
);
281 BE32TOH(part
->pmBootEntry
);
282 BE32TOH(part
->pmBootEntry2
);
283 BE32TOH(part
->pmBootCksum
);
291 fprintf(stderr
, "usage: %s [-fqrw] rawdisk\n",
298 main(int argc
, char **argv
)
301 char name
[MAXPATHLEN
];
302 int force
; /* force label update */
303 int raw
; /* update on-disk label as well */
304 int verbose
; /* verbose output */
305 int write_it
; /* update in-core label if changed */
311 while ((ch
= getopt(argc
, argv
, "fqrw")) != -1) {
334 if ((sd
= opendisk(argv
[0], write_it
? O_RDWR
: O_RDONLY
, name
,
335 (size_t)MAXPATHLEN
, 1)) < 0) {
340 changed
= getparts(sd
, verbose
);
344 showpartitions(stdout
, &label
, 0);
348 if (! changed
&& ! force
)
349 printf("No change; not updating disk label.\n");
352 printf("Updating in-core %sdisk label.\n",
353 raw
? "and on-disk " : "");
357 printf("Not updating disk label.\n");