Annotation of sys/arch/zaurus/stand/zboot/diskprobe.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: diskprobe.c,v 1.3 2006/10/13 00:00:55 krw Exp $ */
2:
3: /*
4: * Copyright (c) 1997 Tobias Weingartner
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: *
28: */
29:
30: /* We want the disk type names from disklabel.h */
31: #undef DKTYPENAMES
32:
33: #include <sys/param.h>
34: #include <sys/queue.h>
35: #include <sys/reboot.h>
36: #include <sys/disklabel.h>
37: #include <stand/boot/bootarg.h>
38: #if 0
39: #include <machine/biosvar.h>
40: #endif
41: #include <lib/libz/zlib.h>
42: #include "disk.h"
43: #if 0
44: #include "biosdev.h"
45: #endif
46: #include "libsa.h"
47:
48: #define MAX_CKSUMLEN MAXBSIZE / DEV_BSIZE /* Max # of blks to cksum */
49:
50: /* Disk spin-up wait timeout. */
51: static u_int timeout = 10;
52:
53: /* Local Prototypes */
54: static void hardprobe(void);
55:
56: /* List of disk devices we found/probed */
57: struct disklist_lh disklist;
58:
59: /*
60: * Probe for all hard disks.
61: */
62: static void
63: hardprobe(void)
64: {
65: struct diskinfo *dip;
66: int i, order[] = { 0x80, 0x82 }; /* XXX probe disks in this order */
67: u_int bsdunit, type;
68: u_int scsi = 0, ide = 0;
69: u_int disk = 0;
70:
71: /* Hard disks */
72: for (i = 0; i < sizeof(order) / sizeof(order[0]); i++) {
73: dip = alloc(sizeof(struct diskinfo));
74: bzero(dip, sizeof(*dip));
75:
76: if (bios_getdiskinfo(order[i], &dip->bios_info) != NULL) {
77: free(dip, 0);
78: continue;
79: }
80:
81: printf("hd%u", disk++);
82:
83: /* Try to find the label, to figure out device type. */
84: if (bios_getdisklabel(&dip->bios_info, &dip->disklabel)
85: == NULL) {
86: printf("*");
87: bsdunit = ide++;
88: type = 0; /* XXX let it be IDE */
89: } else {
90: /* Best guess */
91: switch (dip->disklabel.d_type) {
92: case DTYPE_SCSI:
93: type = 4;
94: bsdunit = scsi++;
95: dip->bios_info.flags |= BDI_GOODLABEL;
96: break;
97:
98: case DTYPE_ESDI:
99: case DTYPE_ST506:
100: type = 0;
101: bsdunit = ide++;
102: dip->bios_info.flags |= BDI_GOODLABEL;
103: break;
104:
105: default:
106: dip->bios_info.flags |= BDI_BADLABEL;
107: type = 0; /* XXX Suggest IDE */
108: bsdunit = ide++;
109: }
110: }
111:
112: dip->bios_info.checksum = 0; /* just in case */
113: /* Fill out best we can. */
114: dip->bios_info.bsd_dev =
115: MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART);
116:
117: /* Add to queue of disks. */
118: TAILQ_INSERT_TAIL(&disklist, dip, list);
119:
120: printf(" ");
121: }
122: }
123:
124: /* Probe for all BIOS supported disks */
125: u_int32_t bios_cksumlen;
126: void
127: diskprobe(void)
128: {
129: struct diskinfo *dip;
130: int i;
131:
132: /* These get passed to kernel */
133: bios_diskinfo_t *bios_diskinfo;
134:
135: /* Init stuff */
136: TAILQ_INIT(&disklist);
137:
138: /* Do probes */
139: hardprobe();
140:
141: #if 0
142: /* Checksumming of hard disks */
143: for (i = 0; disksum(i++) && i < MAX_CKSUMLEN; )
144: ;
145: bios_cksumlen = i;
146:
147: /* Get space for passing bios_diskinfo stuff to kernel */
148: for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
149: dip = TAILQ_NEXT(dip, list))
150: i++;
151: bios_diskinfo = alloc(++i * sizeof(bios_diskinfo_t));
152:
153: /* Copy out the bios_diskinfo stuff */
154: for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
155: dip = TAILQ_NEXT(dip, list))
156: bios_diskinfo[i++] = dip->bios_info;
157:
158: bios_diskinfo[i++].bios_number = -1;
159: /* Register for kernel use */
160: addbootarg(BOOTARG_CKSUMLEN, sizeof(u_int32_t), &bios_cksumlen);
161: addbootarg(BOOTARG_DISKINFO, i * sizeof(bios_diskinfo_t),
162: bios_diskinfo);
163: #endif
164: }
165:
166: /*
167: * Find info on the disk given by major + unit number.
168: */
169: struct diskinfo *
170: dkdevice(dev_t maj, dev_t unit)
171: {
172: struct diskinfo *dip;
173:
174: for (dip = TAILQ_FIRST(&disklist); dip;
175: dip = TAILQ_NEXT(dip, list)) {
176: /* XXX skip non-matching entries according to maj. */
177:
178: if (unit-- == 0)
179: return dip;
180: }
181:
182: return NULL;
183: }
184:
185: /*
186: * Find the Linux device path that corresponds to the given "BIOS" disk,
187: * where 0x80 corresponds to /dev/hda, 0x81 to /dev/hdb, and so on.
188: */
189: void
190: bios_devpath(int dev, int part, char *p)
191: {
192: *p++ = '/';
193: *p++ = 'd';
194: *p++ = 'e';
195: *p++ = 'v';
196: *p++ = '/';
197: if ((dev & 0x80) != 0)
198: *p++ = 'h';
199: else
200: *p++ = 'f';
201: *p++ = 'd';
202: *p++ = 'a' + (dev & 0x7f);
203: if (part != -1)
204: *p++ = '1' + part;
205: *p = '\0';
206: }
207:
208: /*
209: * Fill out a bios_diskinfo_t for this device.
210: */
211: char *
212: bios_getdiskinfo(int dev, bios_diskinfo_t *bdi)
213: {
214: static char path[PATH_MAX];
215: struct linux_stat sb;
216: char *p;
217:
218: bzero(bdi, sizeof *bdi);
219: bdi->bios_number = -1;
220:
221: bios_devpath(dev, -1, path);
222:
223: if (ustat(path, &sb) != 0)
224: return "no device node";
225:
226: bdi->bios_number = dev;
227:
228: if (bios_getdospart(bdi) < 0)
229: return "no OpenBSD partition";
230:
231: return 0;
232: }
233:
234: int
235: bios_getdospart(bios_diskinfo_t *bdi)
236: {
237: char path[PATH_MAX];
238: char buf[DEV_BSIZE];
239: struct dos_partition *dp;
240: int fd;
241: u_int part;
242: size_t rsize;
243:
244: bios_devpath(bdi->bios_number, -1, path);
245:
246: /*
247: * Give disk devices some time to become ready when the first open
248: * fails. Even when open succeeds the disk is sometimes not ready.
249: */
250: if ((fd = uopen(path, O_RDONLY)) == -1 && errno == ENXIO) {
251: int t;
252:
253: while (fd == -1 && timeout > 0) {
254: timeout--;
255: sleep(1);
256: fd = uopen(path, O_RDONLY);
257: }
258: if (fd != -1)
259: sleep(2);
260: }
261: if (fd == -1)
262: return -1;
263:
264: /* Read the disk's MBR. */
265: if (unixstrategy((void *)fd, F_READ, DOSBBSECTOR,
266: DEV_BSIZE, buf, &rsize) != 0 || rsize != DEV_BSIZE) {
267: uclose(fd);
268: errno = EIO;
269: return -1;
270: }
271:
272: /* Find OpenBSD primary partition in the disk's MBR. */
273: dp = (struct dos_partition *)&buf[DOSPARTOFF];
274: for (part = 0; part < NDOSPART; part++)
275: if (dp[part].dp_typ == DOSPTYP_OPENBSD)
276: break;
277: if (part == NDOSPART) {
278: uclose(fd);
279: errno = ERDLAB;
280: return -1;
281: }
282: uclose(fd);
283:
284: return part;
285: }
286:
287: char *
288: bios_getdisklabel(bios_diskinfo_t *bdi, struct disklabel *label)
289: {
290: char path[PATH_MAX];
291: char buf[DEV_BSIZE];
292: int part;
293: int fd;
294: size_t rsize;
295:
296: part = bios_getdospart(bdi);
297: if (part < 0)
298: return "no OpenBSD partition";
299:
300: bios_devpath(bdi->bios_number, part, path);
301:
302: /* Test if the OpenBSD partition has a valid disklabel. */
303: if ((fd = uopen(path, O_RDONLY)) != -1) {
304: char *msg = "failed to read disklabel";
305:
306: if (unixstrategy((void *)fd, F_READ, LABELSECTOR,
307: DEV_BSIZE, buf, &rsize) == 0 && rsize == DEV_BSIZE)
308: msg = getdisklabel(buf, label);
309: uclose(fd);
310: /* Don't wait for other disks if this label is ok. */
311: if (msg == NULL)
312: timeout = 0;
313: return (msg);
314: }
315:
316: return "failed to open partition";
317: }
CVSweb