mbrlabel.c revision 1.10 1 /* $NetBSD: mbrlabel.c,v 1.10 2000/12/24 01:54:20 wiz Exp $ */
2
3 /*
4 * Copyright (C) 1998 Wolfgang Solfrank.
5 * Copyright (C) 1998 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
21 *
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.
32 */
33
34 #include <sys/cdefs.h>
35 #ifndef lint
36 __RCSID("$NetBSD: mbrlabel.c,v 1.10 2000/12/24 01:54:20 wiz Exp $");
37 #endif /* not lint */
38
39 #include <stdio.h>
40 #include <fcntl.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <util.h>
45
46 #include <sys/param.h>
47 #include <sys/disklabel.h>
48 #include <sys/disklabel_mbr.h>
49 #include <sys/ioctl.h>
50
51 #include "dkcksum.h"
52
53 #define FIRSTPART 0
54
55 int main(int, char **);
56 void usage(void);
57 void getlabel(int);
58 void setlabel(int);
59 int getparts(int, int, u_int32_t, u_int32_t);
60 int nbsdtype(int);
61 u_int32_t getlong(void *p);
62
63 struct disklabel label;
64
65 void
66 getlabel(int sd)
67 {
68 struct partition save;
69
70 if (ioctl(sd, DIOCGDINFO, &label) < 0) {
71 perror("get label");
72 exit(1);
73 }
74 save = label.d_partitions[RAW_PART];
75 memset(label.d_partitions, 0, sizeof label.d_partitions);
76 label.d_partitions[RAW_PART] = save;
77 /*
78 * Some ports seem to not set the number of partitions
79 * correctly, albeit they seem to set the raw partiton ok!
80 */
81 if (label.d_npartitions <= RAW_PART)
82 label.d_npartitions = RAW_PART + 1;
83 }
84
85 void
86 setlabel(int sd)
87 {
88 label.d_checksum = 0;
89 label.d_checksum = dkcksum(&label);
90 if (ioctl(sd, DIOCSDINFO, &label) < 0) {
91 perror("set label");
92 exit(1);
93 }
94 }
95
96 static struct typetab {
97 int mbrtype;
98 int nbsdtype;
99 } typetable[] = {
100 { MBR_PTYPE_NETBSD, FS_BSDFFS },
101 { MBR_PTYPE_386BSD, FS_BSDFFS },
102 { MBR_PTYPE_FAT12, FS_MSDOS },
103 { MBR_PTYPE_FAT16S, FS_MSDOS },
104 { MBR_PTYPE_FAT16B, FS_MSDOS },
105 { MBR_PTYPE_FAT32, FS_MSDOS },
106 { MBR_PTYPE_FAT32L, FS_MSDOS },
107 { MBR_PTYPE_FAT16L, FS_MSDOS },
108 { MBR_PTYPE_NTFS, FS_NTFS },
109 { MBR_PTYPE_LNXEXT2, FS_EX2FS },
110 { 0, 0 }
111 };
112
113 int
114 nbsdtype(int type)
115 {
116 struct typetab *tt;
117
118 for (tt = typetable; tt->mbrtype; tt++)
119 if (tt->mbrtype == type)
120 return tt->nbsdtype;
121 return FS_OTHER;
122 }
123
124 u_int32_t
125 getlong(void *p)
126 {
127 unsigned char *cp = p;
128
129 return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
130 }
131
132 int
133 getparts(int sd, int np, u_int32_t off, u_int32_t eoff)
134 {
135 unsigned char buf[DEV_BSIZE];
136 struct mbr_partition parts[NMBRPART];
137 off_t loff = 0; /* XXX this nonsense shuts up GCC 2.7.2.2 */
138 int i;
139
140 loff = (off_t)off * DEV_BSIZE;
141
142 if (lseek(sd, loff, SEEK_SET) != loff) {
143 perror("seek label");
144 exit(1);
145 }
146 if (read(sd, buf, DEV_BSIZE) != DEV_BSIZE) {
147 perror("read label");
148 exit(1);
149 }
150 if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa)
151 return np;
152 memcpy(parts, buf + MBR_PARTOFF, sizeof parts);
153 for (i = 0; i < NMBRPART; i++) {
154 switch (parts[i].mbrp_typ) {
155 case 0:
156 /* Nothing to do */
157 break;
158 case MBR_PTYPE_EXT:
159 case MBR_PTYPE_EXT_LBA:
160 case MBR_PTYPE_EXT_LNX:
161 /* Will be handled below */
162 break;
163 default:
164 label.d_partitions[np].p_size = getlong(&parts[i].mbrp_size);
165 label.d_partitions[np].p_offset = getlong(&parts[i].mbrp_start) + off;
166 label.d_partitions[np].p_fstype = nbsdtype(parts[i].mbrp_typ);
167 switch (label.d_partitions[np].p_fstype) {
168 case FS_BSDFFS:
169 label.d_partitions[np].p_size = 16384;
170 label.d_partitions[np].p_fsize = 1024;
171 label.d_partitions[np].p_frag = 8;
172 label.d_partitions[np].p_cpg = 16;
173 break;
174 #ifdef __does_not_happen__
175 case FS_BSDLFS:
176 label.d_partitions[np].p_size = 16384;
177 label.d_partitions[np].p_fsize = 1024;
178 label.d_partitions[np].p_frag = 8;
179 label.d_partitions[np].p_sgs = XXX;
180 break;
181 #endif
182 }
183 np++;
184 break;
185 }
186 if (np >MAXPARTITIONS)
187 return np;
188 if (np == RAW_PART)
189 np++;
190 }
191 for (i = 0; i < NMBRPART; i++) {
192 u_int32_t poff;
193
194 switch (parts[i].mbrp_typ) {
195 case MBR_PTYPE_EXT:
196 case MBR_PTYPE_EXT_LBA:
197 case MBR_PTYPE_EXT_LNX:
198 poff = getlong(&parts[i].mbrp_start) + eoff;
199 np = getparts(sd, np, poff, eoff ? eoff : poff);
200 break;
201 default:
202 break;
203 }
204 if (np >MAXPARTITIONS)
205 return np;
206 }
207 return np;
208 }
209
210 void
211 usage(void)
212 {
213 fprintf(stderr, "usage: mbrlabel rawdisk\n");
214 exit(1);
215 }
216
217 int
218 main(int argc, char **argv)
219 {
220 int sd;
221 int np;
222 char name[MAXPATHLEN];
223
224 if (argc != 2)
225 usage();
226
227 if ((sd = opendisk(*++argv, O_RDWR, name, MAXPATHLEN, 0)) < 0) {
228 perror(*argv);
229 exit(1);
230 }
231 getlabel(sd);
232 np = getparts(sd, FIRSTPART, MBR_BBSECTOR, 0);
233 if (np > label.d_npartitions)
234 label.d_npartitions = np;
235 setlabel(sd);
236 close(sd);
237 return 0;
238 }
239