1 /* $NetBSD: mbrlabel.c,v 1.25 2005/12/27 15:37:56 jmmv Exp $ */
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.25 2005/12/27 15:37:56 jmmv 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, u_int32_t
, u_int32_t
, int);
63 u_int16_t
getshort(void *);
64 u_int32_t
getlong(void *);
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
);
104 unsigned char *cp
= p
;
106 return (cp
[0] | (cp
[1] << 8));
112 unsigned char *cp
= p
;
114 return (cp
[0] | (cp
[1] << 8) | (cp
[2] << 16) | (cp
[3] << 24));
118 getparts(int sd
, u_int32_t off
, u_int32_t extoff
, int verbose
)
120 unsigned char buf
[DEV_BSIZE
];
121 struct mbr_partition parts
[MBR_PART_COUNT
];
122 struct partition npe
;
124 int i
, j
, unused
, changed
;
127 loff
= (off_t
)off
* DEV_BSIZE
;
129 if (lseek(sd
, loff
, SEEK_SET
) != loff
) {
130 perror("seek label");
133 if (read(sd
, buf
, sizeof buf
) != DEV_BSIZE
) {
134 if (off
!= MBR_BBSECTOR
)
135 perror("read label (sector is possibly out of "
138 perror("read label");
141 if (getshort(buf
+ MBR_MAGIC_OFFSET
) != MBR_MAGIC
)
143 memcpy(parts
, buf
+ MBR_PART_OFFSET
, sizeof parts
);
145 /* scan partition table */
146 for (i
= 0; i
< MBR_PART_COUNT
; i
++) {
147 if (parts
[i
].mbrp_type
== 0 ||
148 /* extended partitions are handled below */
149 MBR_IS_EXTENDED(parts
[i
].mbrp_type
))
152 memset((void *)&npe
, 0, sizeof(npe
));
153 npe
.p_size
= getlong(&parts
[i
].mbrp_size
);
154 npe
.p_offset
= getlong(&parts
[i
].mbrp_start
) + off
;
155 npe
.p_fstype
= xlat_mbr_fstype(parts
[i
].mbrp_type
);
157 /* find existing entry, or first free slot */
158 unused
= -1; /* flag as no free slot */
161 "Found %s partition; size %u (%u MB), offset %u\n",
162 fstypenames
[npe
.p_fstype
],
163 npe
.p_size
, npe
.p_size
/ 2048, npe
.p_offset
);
164 for (j
= 0; j
< label
.d_npartitions
; j
++) {
165 struct partition
*lpe
;
169 lpe
= &label
.d_partitions
[j
];
170 if (lpe
->p_size
== npe
.p_size
&&
171 lpe
->p_offset
== npe
.p_offset
173 && (lpe
->p_fstype
== npe
.p_fstype
||
174 lpe
->p_fstype
== FS_UNUSED
) */
179 " skipping existing %s partition at slot %c.\n",
180 fstypenames
[lpe
->p_fstype
],
182 unused
= -2; /* flag as existing */
185 if (unused
== -1 && lpe
->p_size
== 0 &&
186 lpe
->p_fstype
== FS_UNUSED
)
190 continue; /* entry exists, skip... */
192 if (label
.d_npartitions
< MAXPARTITIONS
) {
193 unused
= label
.d_npartitions
;
194 label
.d_npartitions
++;
197 " WARNING: no slots free for %s partition.\n",
198 fstypenames
[npe
.p_fstype
]);
204 printf(" adding %s partition to slot %c.\n",
205 fstypenames
[npe
.p_fstype
], unused
+ 'a');
206 switch (npe
.p_fstype
) {
209 npe
.p_size
= 16384; /* XXX */
214 #ifdef __does_not_happen__
216 npe
.p_size
= 16384; /* XXX */
224 label
.d_partitions
[unused
] = npe
;
227 /* recursively scan extended partitions */
228 for (i
= 0; i
< MBR_PART_COUNT
; i
++) {
231 if (MBR_IS_EXTENDED(parts
[i
].mbrp_type
)) {
232 poff
= getlong(&parts
[i
].mbrp_start
) + extoff
;
233 changed
+= getparts(sd
, poff
,
234 extoff
? extoff
: poff
, verbose
);
243 fprintf(stderr
, "usage: %s [-fqrw] [-s sector] rawdisk\n",
250 main(int argc
, char **argv
)
253 char *ep
, name
[MAXPATHLEN
];
254 int force
; /* force label update */
255 int raw
; /* update on-disk label as well */
256 int verbose
; /* verbose output */
257 int write_it
; /* update in-core label if changed */
258 uint32_t sector
; /* sector that contains the MBR */
265 sector
= MBR_BBSECTOR
;
266 while ((ch
= getopt(argc
, argv
, "fqrs:w")) != -1) {
279 ulsector
= strtoul(optarg
, &ep
, 10);
280 if (optarg
[0] == '\0' || *ep
!= '\0')
282 "sector number (%s) incorrectly specified",
284 if ((errno
== ERANGE
&& ulsector
== ULONG_MAX
) ||
285 ulsector
> UINT32_MAX
)
287 "sector number (%s) out of range",
289 sector
= (uint32_t)ulsector
;
303 if ((sd
= opendisk(argv
[0], write_it
? O_RDWR
: O_RDONLY
, name
,
304 (size_t)MAXPATHLEN
, 0)) < 0) {
309 changed
= getparts(sd
, sector
, 0, verbose
);
313 showpartitions(stdout
, &label
, 0);
317 if (! changed
&& ! force
)
318 printf("No change; not updating disk label.\n");
321 printf("Updating in-core %sdisk label.\n",
322 raw
? "and on-disk " : "");
326 printf("Not updating disk label.\n");