xref: /netbsd-src/sys/arch/atari/stand/tostools/aptck/disklbl.c (revision 82357f6d420792564499086cb6440ad2fcce8410)
1*82357f6dSdsl /*	$NetBSD: disklbl.c,v 1.6 2009/03/14 21:04:07 dsl Exp $	*/
2cb560ce3Sleo 
3cb560ce3Sleo /*
4cb560ce3Sleo  * Copyright (c) 1995 Waldi Ravens.
5cb560ce3Sleo  * All rights reserved.
6cb560ce3Sleo  *
7cb560ce3Sleo  * Redistribution and use in source and binary forms, with or without
8cb560ce3Sleo  * modification, are permitted provided that the following conditions
9cb560ce3Sleo  * are met:
10cb560ce3Sleo  * 1. Redistributions of source code must retain the above copyright
11cb560ce3Sleo  *    notice, this list of conditions and the following disclaimer.
12cb560ce3Sleo  * 2. Redistributions in binary form must reproduce the above copyright
13cb560ce3Sleo  *    notice, this list of conditions and the following disclaimer in the
14cb560ce3Sleo  *    documentation and/or other materials provided with the distribution.
15cb560ce3Sleo  * 3. All advertising materials mentioning features or use of this software
16cb560ce3Sleo  *    must display the following acknowledgement:
17cb560ce3Sleo  *        This product includes software developed by Waldi Ravens.
18cb560ce3Sleo  * 4. The name of the author may not be used to endorse or promote products
19cb560ce3Sleo  *    derived from this software without specific prior written permission.
20cb560ce3Sleo  *
21cb560ce3Sleo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22cb560ce3Sleo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23cb560ce3Sleo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24cb560ce3Sleo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25cb560ce3Sleo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26cb560ce3Sleo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27cb560ce3Sleo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28cb560ce3Sleo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29cb560ce3Sleo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30cb560ce3Sleo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31cb560ce3Sleo  */
32cb560ce3Sleo 
33cb560ce3Sleo #include <sys/types.h>
34cb560ce3Sleo #include <stdlib.h>
35cb560ce3Sleo #include <stdio.h>
36cb560ce3Sleo #include "libtos.h"
37cb560ce3Sleo #include "aptck.h"
38cb560ce3Sleo #include "ahdilbl.h"
39cb560ce3Sleo #include "disklbl.h"
40cb560ce3Sleo 
41cb560ce3Sleo static int	dkcksum    PROTO((struct disklabel *));
42cb560ce3Sleo static int	bsd_label  PROTO((disk_t *, u_int));
43cb560ce3Sleo static int	ahdi_label PROTO((disk_t *));
44cb560ce3Sleo static int	ahdi_display PROTO((disk_t *));
45cb560ce3Sleo static u_int	ahdi_getparts PROTO((disk_t *, u_int, u_int));
46cb560ce3Sleo 
47cb560ce3Sleo int
readdisklabel(disk_t * dd)48454af1c0Sdsl readdisklabel(disk_t *dd)
49cb560ce3Sleo {
50cb560ce3Sleo 	int	e;
51cb560ce3Sleo 
5289bbb8b2Sleo 	printf("Device     : %s (%s) [%s]\n", dd->sname, dd->fname,
5389bbb8b2Sleo 							 dd->product);
54cb560ce3Sleo 	printf("Medium size: %lu sectors\n", (u_long)dd->msize);
55cb560ce3Sleo 	printf("Sector size: %lu bytes\n\n", (u_long)dd->bsize);
56cb560ce3Sleo 
57cb560ce3Sleo 	e = bsd_label(dd, LABELSECTOR);
58cb560ce3Sleo 	if (e < 0) {
59cb560ce3Sleo 		printf("Device I/O error (hardware problem?)\n\n");
60cb560ce3Sleo 		return(-1);
61cb560ce3Sleo 	}
62cb560ce3Sleo 	if (!e) {
63cb560ce3Sleo 		printf("NetBSD/Atari format, boot block: "
64cb560ce3Sleo 		       "sector %u labeloffset %u\n\n",
65cb560ce3Sleo 		       dd->bblock, dd->lblofs);
66cb560ce3Sleo 		return(0);
67cb560ce3Sleo 	}
68cb560ce3Sleo 
69cb560ce3Sleo 	e = ahdi_label(dd);
70cb560ce3Sleo 	if (e < 0) {
71cb560ce3Sleo 		printf("Device I/O error (hardware problem?)\n\n");
72cb560ce3Sleo 		return(-1);
73cb560ce3Sleo 	}
74cb560ce3Sleo 	if (!e) {
75cb560ce3Sleo 		printf("AHDI format, NetBSD boot block: ");
76cb560ce3Sleo 		if (dd->bblock != NO_BOOT_BLOCK)
77cb560ce3Sleo 			printf("sector %u labeloffset %u\n\n",
78cb560ce3Sleo 			       dd->bblock, dd->lblofs);
79cb560ce3Sleo 		else printf("none\n\n");
80cb560ce3Sleo 		return(0);
81cb560ce3Sleo 	}
82cb560ce3Sleo 
83cb560ce3Sleo 	printf("Unknown label format.\n\n");
84cb560ce3Sleo 	return(-1);
85cb560ce3Sleo }
86cb560ce3Sleo 
87cb560ce3Sleo static int
bsd_label(disk_t * dd,u_int offset)88454af1c0Sdsl bsd_label(disk_t *dd, u_int offset)
89cb560ce3Sleo {
90cb560ce3Sleo 	u_char		*bblk;
91cb560ce3Sleo 	u_int		nsec;
92cb560ce3Sleo 	int		rv;
93cb560ce3Sleo 
9488a221b7Sleo 	nsec = (BBMINSIZE + (dd->bsize - 1)) / dd->bsize;
95cb560ce3Sleo 	bblk = disk_read(dd, offset, nsec);
96cb560ce3Sleo 	if (bblk) {
9789bbb8b2Sleo 		u_int	*end, *p;
98cb560ce3Sleo 
9989bbb8b2Sleo 		end = (u_int *)&bblk[BBMINSIZE - sizeof(struct disklabel)];
100cb560ce3Sleo 		rv  = 1;
10189bbb8b2Sleo 		for (p = (u_int *)bblk; p < end; ++p) {
10289bbb8b2Sleo 			struct disklabel *dl = (struct disklabel *)&p[1];
10389bbb8b2Sleo 			if (  (  (p[0] == NBDAMAGIC && offset == 0)
10489bbb8b2Sleo 			      || (p[0] == AHDIMAGIC && offset != 0)
10589bbb8b2Sleo 			      || (u_char *)dl - bblk == 7168
10689bbb8b2Sleo 			      )
10789bbb8b2Sleo 			   && dl->d_npartitions <= MAXPARTITIONS
10889bbb8b2Sleo 			   && dl->d_magic2 == DISKMAGIC
10989bbb8b2Sleo 			   && dl->d_magic  == DISKMAGIC
11089bbb8b2Sleo 			   && dkcksum(dl)  == 0
11189bbb8b2Sleo 			   )	{
11289bbb8b2Sleo 		    		dd->lblofs = (u_char *)dl - bblk;
113cb560ce3Sleo 		    		dd->bblock = offset;
114cb560ce3Sleo 				rv = 0;
115cb560ce3Sleo 				break;
116cb560ce3Sleo 			}
117cb560ce3Sleo 		}
118cb560ce3Sleo 		free(bblk);
119cb560ce3Sleo 	}
120cb560ce3Sleo 	else rv = -1;
121cb560ce3Sleo 
122cb560ce3Sleo 	return(rv);
123cb560ce3Sleo }
124cb560ce3Sleo 
125cb560ce3Sleo static int
dkcksum(struct disklabel * dl)126454af1c0Sdsl dkcksum(struct disklabel *dl)
127cb560ce3Sleo {
128cb560ce3Sleo 	u_short	*start, *end, sum = 0;
129cb560ce3Sleo 
130cb560ce3Sleo 	start = (u_short *)dl;
131cb560ce3Sleo 	end   = (u_short *)&dl->d_partitions[dl->d_npartitions];
132cb560ce3Sleo 	while (start < end)
133cb560ce3Sleo 		sum ^= *start++;
134cb560ce3Sleo 	return(sum);
135cb560ce3Sleo }
136cb560ce3Sleo 
137cb560ce3Sleo int
ahdi_label(disk_t * dd)138454af1c0Sdsl ahdi_label(disk_t *dd)
139cb560ce3Sleo {
140cb560ce3Sleo 	u_int	i;
141cb560ce3Sleo 	int	e;
142cb560ce3Sleo 
143cb560ce3Sleo 	/*
144cb560ce3Sleo 	 * The AHDI format requires a specific block size.
145cb560ce3Sleo 	 */
146cb560ce3Sleo 	if (dd->bsize != AHDI_BSIZE)
147cb560ce3Sleo 		return(1);
148cb560ce3Sleo 
149cb560ce3Sleo 	/*
150cb560ce3Sleo 	 * Fetch the AHDI partition descriptors.
151cb560ce3Sleo 	 */
152cb560ce3Sleo 	i = ahdi_getparts(dd, AHDI_BBLOCK, AHDI_BBLOCK);
153cb560ce3Sleo 	if (i) {
154cb560ce3Sleo 		if (i < dd->msize)
155cb560ce3Sleo 			return(-1);	/* disk read error		*/
156cb560ce3Sleo 		else return(1);		/* reading past end of medium	*/
157cb560ce3Sleo 	}
158cb560ce3Sleo 
159cb560ce3Sleo 	/*
160cb560ce3Sleo 	 * Display and perform sanity checks.
161cb560ce3Sleo 	 */
162cb560ce3Sleo 	i = ahdi_display(dd);
163cb560ce3Sleo 	if (i)
164cb560ce3Sleo 		return(i);
165cb560ce3Sleo 
166cb560ce3Sleo 	/*
167cb560ce3Sleo 	 * Search for a NetBSD disk label
168cb560ce3Sleo 	 */
169cb560ce3Sleo 	dd->bblock = NO_BOOT_BLOCK;
170cb560ce3Sleo 	for (i = 0; i < dd->nparts; ++i) {
171cb560ce3Sleo 		part_t	*pd = &dd->parts[i];
172cb560ce3Sleo 		u_int	id  = *((u_int32_t *)&pd->id) >> 8;
173cb560ce3Sleo 		if (id == AHDI_PID_NBD || id == AHDI_PID_RAW) {
174cb560ce3Sleo 			u_int	offs = pd->start;
175cb560ce3Sleo 			if ((e = bsd_label(dd, offs)) < 0) {
176cb560ce3Sleo 				return(e);		/* I/O error */
177cb560ce3Sleo 			}
178cb560ce3Sleo 			if (!e) {
179cb560ce3Sleo 				dd->bblock = offs;	/* got it */
180cb560ce3Sleo 				return(0);
181cb560ce3Sleo 			}
182cb560ce3Sleo 			if (id == AHDI_PID_NBD && dd->bblock == NO_BOOT_BLOCK)
183cb560ce3Sleo 				dd->bblock = offs;
184cb560ce3Sleo 		}
185cb560ce3Sleo 	}
186cb560ce3Sleo 	return(0);
187cb560ce3Sleo }
188cb560ce3Sleo 
189cb560ce3Sleo static int
root_cmp(const void * x1,const void * x2)190*82357f6dSdsl root_cmp(const void *x1, const void *x2)
191cb560ce3Sleo {
192cb560ce3Sleo 	const u_int	*r1 = x1,
193cb560ce3Sleo 			*r2 = x2;
194cb560ce3Sleo 
195cb560ce3Sleo 	if (*r1 < *r2)
196cb560ce3Sleo 		return(-1);
197cb560ce3Sleo 	if (*r1 > *r2)
198cb560ce3Sleo 		return(1);
199cb560ce3Sleo 	return(0);
200cb560ce3Sleo }
201cb560ce3Sleo 
202cb560ce3Sleo static int
part_cmp(const void * x1,const void * x2)203*82357f6dSdsl part_cmp(const void *x1, const void *x2)
204cb560ce3Sleo {
205cb560ce3Sleo 	const part_t	*p1 = x1,
206cb560ce3Sleo 			*p2 = x2;
207cb560ce3Sleo 
208cb560ce3Sleo 	if (p1->start < p2->start)
209cb560ce3Sleo 		return(-1);
210cb560ce3Sleo 	if (p1->start > p2->start)
211cb560ce3Sleo 		return(1);
212cb560ce3Sleo 	if (p1->end < p2->end)
213cb560ce3Sleo 		return(-1);
214cb560ce3Sleo 	if (p1->end > p2->end)
215cb560ce3Sleo 		return(1);
216cb560ce3Sleo 	if (p1->rsec < p2->rsec)
217cb560ce3Sleo 		return(-1);
218cb560ce3Sleo 	if (p1->rsec > p2->rsec)
219cb560ce3Sleo 		return(1);
220cb560ce3Sleo 	if (p1->rent < p2->rent)
221cb560ce3Sleo 		return(-1);
222cb560ce3Sleo 	if (p1->rent > p2->rent)
223cb560ce3Sleo 		return(1);
224cb560ce3Sleo 	return(0);
225cb560ce3Sleo }
226cb560ce3Sleo 
227cb560ce3Sleo static int
ahdi_display(disk_t * dd)228454af1c0Sdsl ahdi_display(disk_t *dd)
229cb560ce3Sleo {
230cb560ce3Sleo 	int	i, j, rv = 0;
231cb560ce3Sleo 
232cb560ce3Sleo 	printf("Start of bad sector list : %u\n", dd->bslst);
233cb560ce3Sleo 	if (dd->bslst == 0) {
234cb560ce3Sleo 		printf("* Illegal value (zero) *\n"); rv = 1;
235cb560ce3Sleo 	}
236cb560ce3Sleo 	printf("End of bad sector list   : %u\n", dd->bslend);
237cb560ce3Sleo 	if (dd->bslend == 0) {
238cb560ce3Sleo 		printf("* Illegal value (zero) *\n"); rv = 1;
239cb560ce3Sleo 	}
240cb560ce3Sleo 	printf("Medium size (in root sec): %u\n", dd->hdsize);
241cb560ce3Sleo 	if (dd->hdsize == 0) {
242cb560ce3Sleo 		printf("* Illegal value (zero) *\n"); rv = 1;
243cb560ce3Sleo 	}
244cb560ce3Sleo 
245cb560ce3Sleo 	qsort(dd->roots, dd->nroots, sizeof *dd->roots, root_cmp);
246cb560ce3Sleo 	qsort(dd->parts, dd->nparts, sizeof *dd->parts, part_cmp);
247cb560ce3Sleo 	printf("\n    root  desc   id     start       end    MBs\n");
248cb560ce3Sleo 
249cb560ce3Sleo 	for (i = 0; i < dd->nparts; ++i) {
250cb560ce3Sleo 		part_t	*p1 = &dd->parts[i];
251cb560ce3Sleo 		u_int	megs = p1->end - p1->start + 1,
252cb560ce3Sleo 			blpm = (1024 * 1024) / dd->bsize;
253cb560ce3Sleo 		megs = (megs + (blpm >> 1)) / blpm;
254cb560ce3Sleo 		printf("%8u  %4u  %s  %8u  %8u  (%3u)\n",
255cb560ce3Sleo 			p1->rsec, p1->rent, p1->id,
256cb560ce3Sleo 			p1->start, p1->end, megs);
257cb560ce3Sleo 		for (j = 0; j < dd->nroots; ++j) {
258cb560ce3Sleo 			u_int	aux = dd->roots[j];
259cb560ce3Sleo 			if (aux >= p1->start && aux <= p1->end) {
26079b57114Swiz 				printf("FATAL: auxiliary root at %u\n", aux);
26189bbb8b2Sleo 				rv = 1;
262cb560ce3Sleo 			}
263cb560ce3Sleo 		}
264cb560ce3Sleo 		for (j = i; j--;) {
265cb560ce3Sleo 		    part_t	*p2 = &dd->parts[j];
266cb560ce3Sleo 		    if (p1->start >= p2->start && p1->start <= p2->end) {
26789bbb8b2Sleo 			printf("FATAL: clash with %u/%u\n", p2->rsec, p2->rent);
26889bbb8b2Sleo 			rv = 1;
269cb560ce3Sleo 		    }
270cb560ce3Sleo 		    if (p2->start >= p1->start && p2->start <= p1->end) {
27189bbb8b2Sleo 			printf("FATAL: clash with %u/%u\n", p2->rsec, p2->rent);
27289bbb8b2Sleo 			rv = 1;
273cb560ce3Sleo 		    }
274cb560ce3Sleo 		}
275cb560ce3Sleo 		if (p1->start >= dd->bslst && p1->start <= dd->bslend) {
27689bbb8b2Sleo 		    printf("FATAL: partition overlaps with bad sector list\n");
27789bbb8b2Sleo 		    rv = 1;
278cb560ce3Sleo 		}
279cb560ce3Sleo 		if (dd->bslst >= p1->start && dd->bslst <= p1->end) {
28089bbb8b2Sleo 		    printf("FATAL: partition overlaps with bad sector list\n");
28189bbb8b2Sleo 		    rv = 1;
282cb560ce3Sleo 		}
283cb560ce3Sleo 	}
284cb560ce3Sleo 
28579b57114Swiz 	printf("\nTotal number of auxiliary roots: %u\n", dd->nroots);
286cb560ce3Sleo 	printf("Total number of partitions    : %u\n", dd->nparts);
287cb560ce3Sleo 	if (dd->nparts == 0) {
288cb560ce3Sleo 		printf("* Weird # of partitions (zero) *\n"); rv = 1;
289cb560ce3Sleo 	}
290cb560ce3Sleo 	if (dd->nparts > AHDI_MAXPARTS) {
291cb560ce3Sleo 		printf("* Too many AHDI partitions for the default NetBSD "
292cb560ce3Sleo 			"kernel *\n  Increase MAXAUXROOTS in src/sys/arch/"
293cb560ce3Sleo 			"atari/include/disklabel.h\n  to at least %u, and "
294cb560ce3Sleo 			"recompile the NetBSD kernel.\n", dd->nroots);
295cb560ce3Sleo 		rv = -1;
296cb560ce3Sleo 	}
297cb560ce3Sleo 	return(rv);
298cb560ce3Sleo }
299cb560ce3Sleo 
300cb560ce3Sleo static u_int
ahdi_getparts(dd,rsec,esec)301cb560ce3Sleo ahdi_getparts(dd, rsec, esec)
302cb560ce3Sleo 	disk_t			*dd;
303cb560ce3Sleo 	u_int			rsec,
304cb560ce3Sleo 				esec;
305cb560ce3Sleo {
306cb560ce3Sleo 	struct ahdi_part	*part, *end;
307cb560ce3Sleo 	struct ahdi_root	*root;
308cb560ce3Sleo 	u_int			rv;
309cb560ce3Sleo 
310cb560ce3Sleo 	root = disk_read(dd, rsec, 1);
311cb560ce3Sleo 	if (!root) {
312cb560ce3Sleo 		rv = rsec + (rsec == 0);
313cb560ce3Sleo 		goto done;
314cb560ce3Sleo 	}
315cb560ce3Sleo 
316cb560ce3Sleo 	if (rsec == AHDI_BBLOCK)
317cb560ce3Sleo 		end = &root->ar_parts[AHDI_MAXRPD];
318cb560ce3Sleo 	else end = &root->ar_parts[AHDI_MAXARPD];
319cb560ce3Sleo 	for (part = root->ar_parts; part < end; ++part) {
320cb560ce3Sleo 		u_int	id = *((u_int32_t *)&part->ap_flg);
321cb560ce3Sleo 		if (!(id & 0x01000000))
322cb560ce3Sleo 			continue;
323cb560ce3Sleo 		if ((id &= 0x00ffffff) == AHDI_PID_XGM) {
324cb560ce3Sleo 			u_int	offs = part->ap_offs + esec;
325cb560ce3Sleo 			u_int	i = ++dd->nroots;
326cb560ce3Sleo 			dd->roots = xrealloc(dd->roots, i * sizeof *dd->roots);
327cb560ce3Sleo 			dd->roots[--i] = offs;
32889bbb8b2Sleo 			rv = ahdi_getparts(dd, offs,
32989bbb8b2Sleo 					esec == AHDI_BBLOCK ? offs : esec);
330cb560ce3Sleo 			if (rv)
331cb560ce3Sleo 				goto done;
332cb560ce3Sleo 		} else {
333cb560ce3Sleo 			part_t	*p;
334cb560ce3Sleo 			u_int	i = ++dd->nparts;
335cb560ce3Sleo 			dd->parts = xrealloc(dd->parts, i * sizeof *dd->parts);
336cb560ce3Sleo 			p = &dd->parts[--i];
337cb560ce3Sleo 			*((u_int32_t *)&p->id) = id << 8;
338cb560ce3Sleo 			p->start = part->ap_offs + rsec;
339cb560ce3Sleo 			p->end   = p->start + part->ap_size - 1;
340cb560ce3Sleo 			p->rsec  = rsec;
341cb560ce3Sleo 			p->rent  = part - root->ar_parts;
342cb560ce3Sleo 		}
343cb560ce3Sleo 	}
344cb560ce3Sleo 	dd->hdsize = root->ar_hdsize;
345cb560ce3Sleo 	dd->bslst  = root->ar_bslst;
346cb560ce3Sleo 	dd->bslend = root->ar_bslst + root->ar_bslsize - 1;
347cb560ce3Sleo 	rv = 0;
348cb560ce3Sleo done:
349cb560ce3Sleo 	free(root);
350cb560ce3Sleo 	return(rv);
351cb560ce3Sleo }
352