ahdilabel.c revision 1.2
1/* $NetBSD: ahdilabel.c,v 1.2 2001/02/25 14:32:20 jdc 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
54int		 main (int, char*[]);
55void		 show_parts (struct ahdi_ptable*, int, int, int);
56void		 get_input (char *, int);
57char		*sec_to_cts (struct ahdi_ptable*, u_int32_t, char *);
58u_int32_t	 read_sector (struct ahdi_ptable*,char *);
59void		 change_part (struct ahdi_ptable*, int, int);
60
61int
62main (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 = AHDI_IGN_CKSUM;
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_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
173void
174show_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
239void
240get_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
256char *
257sec_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
272u_int32_t
273read_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, &sector) == 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", &sector) == 1)
292		return (sector);
293	return (0);
294}
295
296void
297change_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