mbrlabel.c revision 1.9 1 /* $NetBSD: mbrlabel.c,v 1.9 2000/12/24 01:50:29 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.9 2000/12/24 01:50:29 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_LNXEXT2, FS_EX2FS },
109 { 0, 0 }
110 };
111
112 int
113 nbsdtype(int type)
114 {
115 struct typetab *tt;
116
117 for (tt = typetable; tt->mbrtype; tt++)
118 if (tt->mbrtype == type)
119 return tt->nbsdtype;
120 return FS_OTHER;
121 }
122
123 u_int32_t
124 getlong(void *p)
125 {
126 unsigned char *cp = p;
127
128 return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
129 }
130
131 int
132 getparts(int sd, int np, u_int32_t off, u_int32_t eoff)
133 {
134 unsigned char buf[DEV_BSIZE];
135 struct mbr_partition parts[NMBRPART];
136 off_t loff = 0; /* XXX this nonsense shuts up GCC 2.7.2.2 */
137 int i;
138
139 loff = (off_t)off * DEV_BSIZE;
140
141 if (lseek(sd, loff, SEEK_SET) != loff) {
142 perror("seek label");
143 exit(1);
144 }
145 if (read(sd, buf, DEV_BSIZE) != DEV_BSIZE) {
146 perror("read label");
147 exit(1);
148 }
149 if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa)
150 return np;
151 memcpy(parts, buf + MBR_PARTOFF, sizeof parts);
152 for (i = 0; i < NMBRPART; i++) {
153 switch (parts[i].mbrp_typ) {
154 case 0:
155 /* Nothing to do */
156 break;
157 case MBR_PTYPE_EXT:
158 case MBR_PTYPE_EXT_LBA:
159 case MBR_PTYPE_EXT_LNX:
160 /* Will be handled below */
161 break;
162 default:
163 label.d_partitions[np].p_size = getlong(&parts[i].mbrp_size);
164 label.d_partitions[np].p_offset = getlong(&parts[i].mbrp_start) + off;
165 label.d_partitions[np].p_fstype = nbsdtype(parts[i].mbrp_typ);
166 switch (label.d_partitions[np].p_fstype) {
167 case FS_BSDFFS:
168 label.d_partitions[np].p_size = 16384;
169 label.d_partitions[np].p_fsize = 1024;
170 label.d_partitions[np].p_frag = 8;
171 label.d_partitions[np].p_cpg = 16;
172 break;
173 #ifdef __does_not_happen__
174 case FS_BSDLFS:
175 label.d_partitions[np].p_size = 16384;
176 label.d_partitions[np].p_fsize = 1024;
177 label.d_partitions[np].p_frag = 8;
178 label.d_partitions[np].p_sgs = XXX;
179 break;
180 #endif
181 }
182 np++;
183 break;
184 }
185 if (np >MAXPARTITIONS)
186 return np;
187 if (np == RAW_PART)
188 np++;
189 }
190 for (i = 0; i < NMBRPART; i++) {
191 u_int32_t poff;
192
193 switch (parts[i].mbrp_typ) {
194 case MBR_PTYPE_EXT:
195 case MBR_PTYPE_EXT_LBA:
196 case MBR_PTYPE_EXT_LNX:
197 poff = getlong(&parts[i].mbrp_start) + eoff;
198 np = getparts(sd, np, poff, eoff ? eoff : poff);
199 break;
200 default:
201 break;
202 }
203 if (np >MAXPARTITIONS)
204 return np;
205 }
206 return np;
207 }
208
209 void
210 usage(void)
211 {
212 fprintf(stderr, "usage: mbrlabel rawdisk\n");
213 exit(1);
214 }
215
216 int
217 main(int argc, char **argv)
218 {
219 int sd;
220 int np;
221 char name[MAXPATHLEN];
222
223 if (argc != 2)
224 usage();
225
226 if ((sd = opendisk(*++argv, O_RDWR, name, MAXPATHLEN, 0)) < 0) {
227 perror(*argv);
228 exit(1);
229 }
230 getlabel(sd);
231 np = getparts(sd, FIRSTPART, MBR_BBSECTOR, 0);
232 if (np > label.d_npartitions)
233 label.d_npartitions = np;
234 setlabel(sd);
235 close(sd);
236 return 0;
237 }
238