ahdilabel.c revision 1.1 1 /* $NetBSD: ahdilabel.c,v 1.1 2000/08/07 09:23:40 leo Exp $ */
2
3 /*
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Julian Coleman.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "privahdi.h"
40 #include <ctype.h>
41 #include <errno.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <strings.h>
45
46 /*
47 * I think we can safely assume a fixed blocksize - AHDI won't support
48 * something different...
49 */
50 #define BLPM ((1024 * 1024) / DEV_BSIZE)
51 #define UNITS_SECTORS 0
52 #define UNITS_CTS 1
53
54 int main (int, char*[]);
55 void show_parts (struct ahdi_ptable*, int, int, int);
56 void get_input (char *, int);
57 char *sec_to_cts (struct ahdi_ptable*, u_int32_t, char *);
58 u_int32_t read_sector (struct ahdi_ptable*,char *);
59 void change_part (struct ahdi_ptable*, int, int);
60
61 int
62 main (argc, argv)
63 int argc;
64 char *argv[];
65 {
66 struct ahdi_ptable ptable;
67 int flags, rv, key, units;
68
69 if (argc < 2) {
70 fprintf (stderr, "usage: %s raw_disk\n", argv[0]);
71 exit (EXIT_FAILURE);
72 }
73
74 flags = 0;
75 while ((rv = ahdi_readlabel(&ptable, argv[1], flags)) != 1) {
76 switch (rv) {
77 case -1:
78 fprintf (stderr,
79 "%s: %s: %s\n", argv[0], argv[1],
80 strerror (errno));
81 exit (EXIT_FAILURE);
82 break;
83 case -2:
84 fprintf (stderr,
85 "%s: disk not 512 bytes/sector\n", argv[0]);
86 exit (EXIT_FAILURE);
87 break;
88 case -3:
89 printf ("No AHDI partitions found. Continue (y/N)?");
90 if (toupper(getchar()) == 'Y') {
91 (void) fpurge(stdin);
92 flags |= FORCE_AHDI;
93 } else
94 exit (EXIT_FAILURE);
95 break;
96 case -4:
97 case -5:
98 case -6:
99 printf ("Errors reading AHDI partition table. Override (y/N)? ");
100 if (toupper(getchar()) == 'Y') {
101 (void) fpurge(stdin);
102 flags |= AHDI_IGN_EXISTS | AHDI_IGN_EXT |
103 AHDI_IGN_CKSUM | AHDI_IGN_SPU;
104 } else
105 exit (EXIT_FAILURE);
106 break;
107 case 1:
108 /* Everything is OK */
109 break;
110 default:
111 exit (EXIT_FAILURE);
112 break;
113 }
114 }
115
116 units = UNITS_SECTORS;
117 show_parts (&ptable, 0, ptable.nparts, units);
118 key = 0;
119 while (key != 'Q') {
120 (void) fpurge(stdin);
121 printf ("Change [a-p], r)ecalculate, s)how, u)nits, w)rite or q)uit ");
122 key = toupper(getchar());
123 if (key == EOF)
124 key = 'Q';
125 if (key >= 'A' && key <= 'P') {
126 change_part (&ptable, key - 'A', units);
127 }
128 if (key == 'R') {
129 if (ahdi_buildlabel (&ptable))
130 printf ("Partiton table adjusted\n");
131 }
132 if (key == 'S') {
133 show_parts (&ptable, 0, ptable.nparts, units);
134 }
135 if (key == 'U') {
136 if (units == UNITS_SECTORS)
137 units = UNITS_CTS;
138 else
139 units = UNITS_SECTORS;
140 }
141 if (key == 'W') {
142 if ((rv = ahdi_writelabel (&ptable, argv[1], 0)) < 0) {
143 if (rv == -1)
144 perror ("\0");
145 if (rv == -2)
146 printf ("Invalid number of partitions!\n");
147 if (rv == -3)
148 printf ("GEM partition should be BGM or BGM partition should be GEM!\n");
149 if (rv == -4)
150 printf ("Partition overlaps root sector or bad sector list (starts before sector 2)!\n");
151 if (rv == -5)
152 printf ("Partition extends past end of disk!\n");
153 if (rv == -6)
154 printf ("Partitions overlap!\n");
155 if (rv == -7)
156 printf ("Partition overlaps auxilliary root!\n");
157 if (rv == -8)
158 printf ("More than 4 partitions in root sector!\n");
159 if (rv == -9)
160 printf ("More than 1 partition in an auxiliary root!\n");
161 if (rv < -1 && ahdi_errp1 != -1)
162 printf ("\tpartition %c has errors.\n",
163 ahdi_errp1 + 'a');
164 if (rv < -1 && ahdi_errp2 != -1)
165 printf ("\tpartition %c has errors.\n",
166 ahdi_errp2 + 'a');
167 }
168 }
169 }
170 return (0);
171 }
172
173 void
174 show_parts (ptable, start, finish, units)
175 struct ahdi_ptable *ptable;
176 int start, finish, units;
177 {
178 int i;
179
180 printf ("Disk information :\n");
181 printf (" sectors/track: %d\n", ptable->nsectors);
182 printf (" tracks/cylinder: %d\n", ptable->ntracks);
183 printf (" sectors/cylinder: %d\n", ptable->secpercyl);
184 printf (" cylinders: %d\n", ptable->ncylinders);
185 printf (" total sectors: %d\n", ptable->secperunit);
186
187 if (units == UNITS_SECTORS) {
188 printf (" # id root start end size MBs\n");
189 for (i = start; i < finish; i++) {
190 printf (" %c %c%c%c %8u %8u %8u %8u (%4u)\n",
191 i + 'a', ptable->parts[i].id[0],
192 ptable->parts[i].id[1], ptable->parts[i].id[2],
193 ptable->parts[i].root, ptable->parts[i].start,
194 ptable->parts[i].start +
195 (ptable->parts[i].size ?
196 ptable->parts[i].size - 1 : 0),
197 ptable->parts[i].size,
198 (ptable->parts[i].size + (BLPM >> 1)) / BLPM);
199 }
200 } else {
201 u_int32_t cylinder, track, sector;
202 printf (" # id root start end size MBs\n");
203 for (i = start; i < finish; i++) {
204 printf (" %c %c%c%c ", i + 'a',
205 ptable->parts[i].id[0], ptable->parts[i].id[1],
206 ptable->parts[i].id[2]);
207 sector = ptable->parts[i].root;
208 cylinder = sector / ptable->secpercyl;
209 sector -= cylinder * ptable->secpercyl;
210 track = sector / ptable->nsectors;
211 sector -= track * ptable->nsectors;
212 printf ("%5u/%2u/%3u ", cylinder, track, sector);
213 sector = ptable->parts[i].start;
214 cylinder = sector / ptable->secpercyl;
215 sector -= cylinder * ptable->secpercyl;
216 track = sector / ptable->nsectors;
217 sector -= track * ptable->nsectors;
218 printf ("%5u/%2u/%3u ", cylinder, track, sector);
219 sector = ptable->parts[i].start +
220 (ptable->parts[i].size ?
221 ptable->parts[i].size - 1 : 0),
222 cylinder = sector / ptable->secpercyl;
223 sector -= cylinder * ptable->secpercyl;
224 track = sector / ptable->nsectors;
225 sector -= track * ptable->nsectors;
226 printf ("%5u/%2u/%3u ", cylinder, track, sector);
227 sector = ptable->parts[i].size;
228 cylinder = sector / ptable->secpercyl;
229 sector -= cylinder * ptable->secpercyl;
230 track = sector / ptable->nsectors;
231 sector -= track * ptable->nsectors;
232 printf ("%5u/%2u/%3u ", cylinder, track, sector);
233 printf ("(%4u)\n",
234 (ptable->parts[i].size + (BLPM >> 1)) / BLPM);
235 }
236 }
237 }
238
239 void
240 get_input (buf, len)
241 char *buf;
242 int len;
243 {
244 int count, key;
245
246 count = 0;
247 (void) fpurge(stdin);
248 while (count < (len - 1) && key != '\n' && key != '\r') {
249 key = getchar();
250 buf[count] = key;
251 count++;
252 }
253 buf[count] = '\0';
254 }
255
256 char *
257 sec_to_cts (ptable, sector, cts)
258 struct ahdi_ptable *ptable;
259 u_int32_t sector;
260 char *cts;
261 {
262 u_int32_t cylinder, track;
263
264 cylinder = sector / ptable->secpercyl;
265 sector -= cylinder * ptable->secpercyl;
266 track = sector / ptable->nsectors;
267 sector -= track * ptable->nsectors;
268 sprintf (cts, "%u/%u/%u", cylinder, track, sector);
269 return (cts);
270 }
271
272 u_int32_t
273 read_sector (ptable, buf)
274 struct ahdi_ptable *ptable;
275 char *buf;
276 {
277 u_int32_t sector, track, cylinder;
278
279 sector = track = cylinder = 0;
280 if ((strchr (buf, '/') != NULL) &&
281 ((sscanf (buf, "%u/%u/%u", &cylinder, &track, §or) == 3) ||
282 (sscanf (buf, "%u/%u/", &cylinder, &track) == 2) ||
283 (sscanf (buf, "%u/", &cylinder) == 1))) {
284 if (sector > ptable->nsectors || track > ptable->ntracks ||
285 cylinder > ptable->ncylinders)
286 return (0);
287 sector += ptable->nsectors * track;
288 sector += ptable->secpercyl * cylinder;
289 return (sector);
290 }
291 if (sscanf (buf, "%u", §or) == 1)
292 return (sector);
293 return (0);
294 }
295
296 void
297 change_part (ptable, part, units)
298 struct ahdi_ptable *ptable;
299 int part, units;
300 {
301 #define BUFLEN 20
302 #define CTSLEN 64
303 char buf[BUFLEN], cts[CTSLEN];
304 u_int32_t sector;
305
306 if (part > ptable->nparts) {
307 part = ptable->nparts;
308 printf ("Changing partition %c!\n", part + 'a');
309 ptable->nparts++;
310 }
311 if (part == ptable->nparts)
312 ptable->nparts++;
313 show_parts (ptable, part, part + 1, units);
314
315 printf ("id [%c%c%c] ", ptable->parts[part].id[0],
316 ptable->parts[part].id[1], ptable->parts[part].id[2]);
317 get_input (&buf[0], BUFLEN);
318 if (buf[0] != '\n' && buf[0] != '\r') {
319 ptable->parts[part].id[0] = buf[0];
320 ptable->parts[part].id[1] = buf[1];
321 ptable->parts[part].id[2] = buf[2];
322 }
323
324 printf ("root [%8u (%s)] ", ptable->parts[part].root,
325 sec_to_cts (ptable, ptable->parts[part].root, &cts[0]));
326 get_input (&buf[0], BUFLEN);
327 if (buf[0] != '\n' && buf[0] != '\r') {
328 sector = read_sector (ptable, buf);
329 ptable->parts[part].root = sector;
330 }
331
332 printf ("start [%8u (%s)] ", ptable->parts[part].start,
333 sec_to_cts (ptable, ptable->parts[part].start, &cts[0]));
334 get_input (&buf[0], BUFLEN);
335 if (buf[0] != '\n' && buf[0] != '\r') {
336 sector = read_sector (ptable, buf);
337 if (sector)
338 ptable->parts[part].start = sector;
339 }
340
341 printf ("size [%8u (%s)] ", ptable->parts[part].size,
342 sec_to_cts (ptable, ptable->parts[part].size, &cts[0]));
343 get_input (&buf[0], BUFLEN);
344 if (buf[0] != '\n' && buf[0] != '\r') {
345 sector = read_sector (ptable, buf);
346 if (sector)
347 ptable->parts[part].size = sector;
348 }
349
350 /*
351 printf ("NetBSD disk letter [%c] ", ptable->parts[part].letter + 'a');
352 get_input (&buf[0], BUFLEN);
353 if (buf[0] != '\n' && buf[0] != '\r')
354 if (buf[0] == 'a' || (buf[0] >= 'd' && buf[0] <= 'p'))
355 ptable->parts[part].letter = buf[0] - 'a';
356 */
357
358 if (!ptable->parts[part].start && !ptable->parts[part].size) {
359 if (part == ptable->nparts - 1)
360 ptable->nparts--;
361 }
362 }
363