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