1 /* $NetBSD: ofdev.c,v 1.21 2009/01/12 07:05:22 tsutsui Exp $ */
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Device I/O routines using Open Firmware
40 #include <sys/param.h>
41 #include <sys/disklabel.h>
42 #include <sys/bootblock.h>
44 #include <netinet/in.h>
46 #include <lib/libkern/libkern.h>
48 #include <lib/libsa/stand.h>
49 #include <lib/libsa/byteorder.h>
50 #include <lib/libsa/cd9660.h>
51 #include <lib/libsa/nfs.h>
52 #include <lib/libsa/ufs.h>
53 #include <lib/libsa/lfs.h>
54 #include <lib/libsa/ustarfs.h>
60 # define DPRINTF printf
62 # define DPRINTF while (0) printf
66 strategy(void *devdata
, int rw
, daddr_t blk
, size_t size
, void *buf
,
69 struct of_dev
*dev
= devdata
;
75 if (dev
->type
!= OFDEV_DISK
)
78 pos
= (u_quad_t
)(blk
+ dev
->partoff
) * dev
->bsize
;
81 if (OF_seek(dev
->handle
, pos
) < 0)
83 n
= OF_read(dev
->handle
, buf
, size
);
95 devopen_dummy(struct open_file
*of
, ...) {
100 devclose(struct open_file
*of
)
102 struct of_dev
*op
= of
->f_devdata
;
104 if (op
->type
== OFDEV_NET
)
106 OF_call_method("dma-free", op
->handle
, 2, 0, op
->dmabuf
, MAXPHYS
);
107 OF_close(op
->handle
);
112 static struct devsw of_devsw
[1] = {
113 { "OpenFirmware", strategy
, devopen_dummy
, devclose
, noioctl
}
115 int ndevs
= sizeof of_devsw
/ sizeof of_devsw
[0];
117 static struct fs_ops file_system_ffsv1
= FS_OPS(ffsv1
);
118 static struct fs_ops file_system_ffsv2
= FS_OPS(ffsv2
);
119 static struct fs_ops file_system_lfsv1
= FS_OPS(lfsv1
);
120 static struct fs_ops file_system_lfsv2
= FS_OPS(lfsv2
);
121 static struct fs_ops file_system_hfs
= FS_OPS(hfs
);
122 static struct fs_ops file_system_ustarfs
= FS_OPS(ustarfs
);
123 static struct fs_ops file_system_cd9660
= FS_OPS(cd9660
);
124 static struct fs_ops file_system_nfs
= FS_OPS(nfs
);
126 struct fs_ops file_system
[8];
129 static struct of_dev ofdev
= {
133 char opened_name
[MAXBOOTPATHLEN
];
136 get_long(const void *p
)
138 const unsigned char *cp
= p
;
140 return cp
[0] | (cp
[1] << 8) | (cp
[2] << 16) | (cp
[3] << 24);
144 * Find a valid disklabel.
147 search_label(struct of_dev
*devp
, u_long off
, char *buf
, struct disklabel
*lp
,
151 struct mbr_partition
*p
;
154 static int recursion
;
156 if (strategy(devp
, F_READ
, off
, DEV_BSIZE
, buf
, &nread
)
157 || nread
!= DEV_BSIZE
)
160 if (*(u_int16_t
*)&buf
[MBR_MAGIC_OFFSET
] != sa_htole16(MBR_MAGIC
))
163 if (recursion
++ <= 1)
165 for (p
= (struct mbr_partition
*)(buf
+ MBR_PART_OFFSET
), i
= 4;
167 if (p
->mbrp_type
== MBR_PTYPE_NETBSD
168 #ifdef COMPAT_386BSD_MBRPART
169 || (p
->mbrp_type
== MBR_PTYPE_386BSD
&&
170 (printf("WARNING: old BSD partition ID!\n"), 1)
171 /* XXX XXX - libsa printf() is void */ )
174 poff
= get_long(&p
->mbrp_start
) + off0
;
175 if (strategy(devp
, F_READ
, poff
+ 1,
176 DEV_BSIZE
, buf
, &nread
) == 0
177 && nread
== DEV_BSIZE
) {
178 if (!getdisklabel(buf
, lp
)) {
183 if (strategy(devp
, F_READ
, off
, DEV_BSIZE
, buf
, &nread
)
184 || nread
!= DEV_BSIZE
) {
188 } else if (p
->mbrp_type
== MBR_PTYPE_EXT
) {
189 poff
= get_long(&p
->mbrp_start
);
190 if (!search_label(devp
, poff
, buf
, lp
, off0
)) {
194 if (strategy(devp
, F_READ
, off
, DEV_BSIZE
, buf
, &nread
)
195 || nread
!= DEV_BSIZE
) {
207 parsefilepath(const char *path
, char *devname
, char *fname
, char *ppart
)
212 char str
[MAXBOOTPATHLEN
];
215 DPRINTF("%s: path = %s\n", __func__
, path
);
226 strlcpy(str
, path
, sizeof(str
));
228 for (cp
= str
; *cp
!= '\0'; lp
= cp
) {
229 /* For each component of the path name... */
230 while (*++cp
!= '\0' && *cp
!= '/')
234 /* ...look whether there is a device with this name */
235 dhandle
= OF_finddevice(str
);
236 DPRINTF("%s: Checking %s: dhandle = %d\n",
237 __func__
, str
, dhandle
);
241 * If it's a vaild device, lp is a delimiter
242 * in the OF device path.
244 if (OF_getprop(dhandle
, "device_type", devtype
,
251 * If not, lp is the delimiter between OF device path
252 * and the specified filename.
255 /* Check if the last component was a block device... */
256 if (strcmp(devtype
, "block") == 0) {
257 /* search for arguments */
259 --cp
>= str
&& *cp
!= '/' && *cp
!= ':';)
261 if (cp
>= str
&& *cp
== ':') {
262 /* found arguments */
264 *--cp
!= ':' && *cp
!= ',';)
267 *cp
<= 'a' + MAXPARTITIONS
&&
274 DPRINTF("%s: filename = %s\n", __func__
, lp
);
278 /* set device path */
280 DPRINTF("%s: device path = %s\n",
283 strcpy(devname
, str
);
289 DPRINTF("%s: invalid path?\n", __func__
);
294 devopen(struct open_file
*of
, const char *name
, char **file
)
298 char devname
[MAXBOOTPATHLEN
];
299 char filename
[MAXBOOTPATHLEN
];
301 struct disklabel label
;
306 if (ofdev
.handle
!= -1)
308 if (of
->f_flags
!= F_READ
)
311 if (!parsefilepath(name
, devname
, filename
, &partition
))
314 if (filename
[0] == '\0')
318 if (devname
[0] == '\0')
319 /* no device, use default bootdev */
320 strlcpy(devname
, bootdev
, sizeof(devname
));
322 DPRINTF("%s: devname = %s, filename = %s\n",
323 __func__
, devname
, filename
);
325 strlcpy(opened_name
, devname
, sizeof(opened_name
));
327 cp
= opened_name
+ strlen(opened_name
);
332 if (filename
[0] != '/')
333 strlcat(opened_name
, "/", sizeof(opened_name
));
334 strlcat(opened_name
, filename
, sizeof(opened_name
));
336 DPRINTF("%s: opened_name = %s\n", __func__
, opened_name
);
338 *file
= opened_name
+ strlen(devname
) + 1;
339 if ((handle
= OF_finddevice(devname
)) == -1)
341 if (OF_getprop(handle
, "device_type", buf
, sizeof buf
) < 0)
344 if (!strcmp(buf
, "block"))
346 * For block devices, indicate raw partition
347 * (:0 in OpenFirmware)
349 strlcat(devname
, ":0", sizeof(devname
));
351 if ((handle
= OF_open(devname
)) == -1)
353 memset(&ofdev
, 0, sizeof ofdev
);
354 ofdev
.handle
= handle
;
356 OF_call_method("dma-alloc", handle
, 1, 1, MAXPHYS
, &ofdev
.dmabuf
);
357 if (!strcmp(buf
, "block")) {
358 ofdev
.type
= OFDEV_DISK
;
359 ofdev
.bsize
= DEV_BSIZE
;
360 /* First try to find a disklabel without MBR partitions */
361 if (strategy(&ofdev
, F_READ
,
362 LABELSECTOR
, DEV_BSIZE
, buf
, &nread
) != 0
363 || nread
!= DEV_BSIZE
364 || getdisklabel(buf
, &label
)) {
365 /* Else try MBR partitions */
366 error
= search_label(&ofdev
, 0, buf
, &label
, 0);
367 if (error
&& error
!= ERDLAB
)
371 if (error
== ERDLAB
) {
374 * User specified a parititon,
378 /* No, label, just use complete disk */
381 part
= partition
? partition
- 'a' : 0;
382 ofdev
.partoff
= label
.d_partitions
[part
].p_offset
;
385 of
->f_dev
= of_devsw
;
386 of
->f_devdata
= &ofdev
;
387 file_system
[0] = file_system_ffsv1
;
388 file_system
[1] = file_system_ffsv2
;
389 file_system
[2] = file_system_lfsv1
;
390 file_system
[3] = file_system_lfsv2
;
391 file_system
[4] = file_system_ustarfs
;
392 file_system
[5] = file_system_cd9660
;
393 file_system
[6] = file_system_hfs
;
397 if (!strcmp(buf
, "network")) {
398 ofdev
.type
= OFDEV_NET
;
399 of
->f_dev
= of_devsw
;
400 of
->f_devdata
= &ofdev
;
401 file_system
[0] = file_system_nfs
;
403 if ((error
= net_open(&ofdev
)))