1 1.31 andvar /* $NetBSD: ofdev.c,v 1.31 2024/02/10 18:43:51 andvar Exp $ */ 2 1.1 tsubai 3 1.1 tsubai /* 4 1.1 tsubai * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 1.1 tsubai * Copyright (C) 1995, 1996 TooLs GmbH. 6 1.1 tsubai * All rights reserved. 7 1.1 tsubai * 8 1.1 tsubai * Redistribution and use in source and binary forms, with or without 9 1.1 tsubai * modification, are permitted provided that the following conditions 10 1.1 tsubai * are met: 11 1.1 tsubai * 1. Redistributions of source code must retain the above copyright 12 1.1 tsubai * notice, this list of conditions and the following disclaimer. 13 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 tsubai * notice, this list of conditions and the following disclaimer in the 15 1.1 tsubai * documentation and/or other materials provided with the distribution. 16 1.1 tsubai * 3. All advertising materials mentioning features or use of this software 17 1.1 tsubai * must display the following acknowledgement: 18 1.1 tsubai * This product includes software developed by TooLs GmbH. 19 1.1 tsubai * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 1.1 tsubai * derived from this software without specific prior written permission. 21 1.1 tsubai * 22 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 1.1 tsubai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 tsubai * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 tsubai * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 1.1 tsubai * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 1.1 tsubai * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 1.1 tsubai * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 1.1 tsubai * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 1.1 tsubai * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 1.1 tsubai * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 tsubai */ 33 1.1 tsubai /* 34 1.1 tsubai * Device I/O routines using Open Firmware 35 1.1 tsubai */ 36 1.1 tsubai 37 1.14 aymeric #include "ofdev.h" 38 1.17 uwe #include "openfirm.h" 39 1.14 aymeric 40 1.1 tsubai #include <sys/param.h> 41 1.1 tsubai #include <sys/disklabel.h> 42 1.13 lukem #include <sys/bootblock.h> 43 1.1 tsubai 44 1.1 tsubai #include <netinet/in.h> 45 1.1 tsubai 46 1.18 uwe #include <lib/libkern/libkern.h> 47 1.18 uwe 48 1.1 tsubai #include <lib/libsa/stand.h> 49 1.18 uwe #include <lib/libsa/byteorder.h> 50 1.1 tsubai #include <lib/libsa/cd9660.h> 51 1.25 matt #include <lib/libsa/dosfs.h> 52 1.1 tsubai #include <lib/libsa/nfs.h> 53 1.7 tsubai #include <lib/libsa/ufs.h> 54 1.20 hauke #include <lib/libsa/lfs.h> 55 1.9 tsutsui #include <lib/libsa/ustarfs.h> 56 1.1 tsubai 57 1.7 tsubai #include "hfs.h" 58 1.17 uwe #include "net.h" 59 1.1 tsubai 60 1.22 tsutsui #ifdef DEBUG 61 1.22 tsutsui # define DPRINTF printf 62 1.22 tsutsui #else 63 1.22 tsutsui # define DPRINTF while (0) printf 64 1.22 tsutsui #endif 65 1.1 tsubai 66 1.1 tsubai static int 67 1.12 aymeric strategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf, 68 1.12 aymeric size_t *rsize) 69 1.1 tsubai { 70 1.1 tsubai struct of_dev *dev = devdata; 71 1.1 tsubai u_quad_t pos; 72 1.1 tsubai int n; 73 1.8 tsutsui 74 1.1 tsubai if (rw != F_READ) 75 1.1 tsubai return EPERM; 76 1.1 tsubai if (dev->type != OFDEV_DISK) 77 1.1 tsubai panic("strategy"); 78 1.8 tsutsui 79 1.1 tsubai pos = (u_quad_t)(blk + dev->partoff) * dev->bsize; 80 1.8 tsutsui 81 1.1 tsubai for (;;) { 82 1.1 tsubai if (OF_seek(dev->handle, pos) < 0) 83 1.1 tsubai break; 84 1.1 tsubai n = OF_read(dev->handle, buf, size); 85 1.1 tsubai if (n == -2) 86 1.1 tsubai continue; 87 1.1 tsubai if (n < 0) 88 1.1 tsubai break; 89 1.1 tsubai *rsize = n; 90 1.1 tsubai return 0; 91 1.1 tsubai } 92 1.1 tsubai return EIO; 93 1.1 tsubai } 94 1.1 tsubai 95 1.1 tsubai static int 96 1.14 aymeric devopen_dummy(struct open_file *of, ...) { 97 1.14 aymeric return -1; 98 1.14 aymeric } 99 1.14 aymeric 100 1.14 aymeric static int 101 1.14 aymeric devclose(struct open_file *of) 102 1.1 tsubai { 103 1.28 thorpej uint32_t cells[2]; 104 1.1 tsubai struct of_dev *op = of->f_devdata; 105 1.8 tsutsui 106 1.29 martin cells[0] = (uintptr_t)op->dmabuf; 107 1.28 thorpej cells[1] = MAXPHYS; 108 1.28 thorpej 109 1.1 tsubai if (op->type == OFDEV_NET) 110 1.1 tsubai net_close(op); 111 1.28 thorpej OF_call_method("dma-free", op->handle, 2, 0, (int *)cells); 112 1.1 tsubai OF_close(op->handle); 113 1.1 tsubai op->handle = -1; 114 1.17 uwe return 0; 115 1.1 tsubai } 116 1.1 tsubai 117 1.19 mrg static struct devsw of_devsw[1] = { 118 1.17 uwe { "OpenFirmware", strategy, devopen_dummy, devclose, noioctl } 119 1.1 tsubai }; 120 1.19 mrg int ndevs = sizeof of_devsw / sizeof of_devsw[0]; 121 1.1 tsubai 122 1.20 hauke static struct fs_ops file_system_ffsv1 = FS_OPS(ffsv1); 123 1.20 hauke static struct fs_ops file_system_ffsv2 = FS_OPS(ffsv2); 124 1.20 hauke static struct fs_ops file_system_lfsv1 = FS_OPS(lfsv1); 125 1.20 hauke static struct fs_ops file_system_lfsv2 = FS_OPS(lfsv2); 126 1.15 junyoung static struct fs_ops file_system_hfs = FS_OPS(hfs); 127 1.15 junyoung static struct fs_ops file_system_ustarfs = FS_OPS(ustarfs); 128 1.15 junyoung static struct fs_ops file_system_cd9660 = FS_OPS(cd9660); 129 1.15 junyoung static struct fs_ops file_system_nfs = FS_OPS(nfs); 130 1.25 matt static struct fs_ops file_system_dosfs = FS_OPS(dosfs); 131 1.1 tsubai 132 1.25 matt struct fs_ops file_system[9]; 133 1.1 tsubai int nfsys; 134 1.1 tsubai 135 1.1 tsubai static struct of_dev ofdev = { 136 1.1 tsubai -1, 137 1.1 tsubai }; 138 1.1 tsubai 139 1.22 tsutsui char opened_name[MAXBOOTPATHLEN]; 140 1.1 tsubai 141 1.23 phx /* 142 1.23 phx * Check if this APM partition is a suitable root partition and return 143 1.23 phx * its file system type or zero. 144 1.23 phx */ 145 1.23 phx static u_int8_t 146 1.23 phx check_apm_root(struct part_map_entry *part, int *clust) 147 1.23 phx { 148 1.23 phx struct blockzeroblock *bzb; 149 1.23 phx char typestr[32], *s; 150 1.23 phx u_int8_t fstype; 151 1.23 phx 152 1.23 phx *clust = 0; /* may become 1 for A/UX partitions */ 153 1.23 phx fstype = 0; 154 1.23 phx bzb = (struct blockzeroblock *)(&part->pmBootArgs); 155 1.23 phx 156 1.23 phx /* convert partition type name to upper case */ 157 1.23 phx strncpy(typestr, (char *)part->pmPartType, sizeof(typestr)); 158 1.23 phx typestr[sizeof(typestr) - 1] = '\0'; 159 1.23 phx for (s = typestr; *s; s++) 160 1.23 phx if ((*s >= 'a') && (*s <= 'z')) 161 1.23 phx *s = (*s - 'a' + 'A'); 162 1.23 phx 163 1.23 phx if (strcmp(PART_TYPE_NBSD_PPCBOOT, typestr) == 0) { 164 1.23 phx if ((bzb->bzbMagic == BZB_MAGIC) && 165 1.23 phx (bzb->bzbType < FSMAXTYPES)) 166 1.23 phx fstype = bzb->bzbType; 167 1.23 phx else 168 1.23 phx fstype = FS_BSDFFS; 169 1.23 phx } else if (strcmp(PART_TYPE_UNIX, typestr) == 0 && 170 1.23 phx bzb->bzbMagic == BZB_MAGIC && (bzb->bzbFlags & BZB_ROOTFS)) { 171 1.23 phx *clust = bzb->bzbCluster; 172 1.23 phx fstype = FS_BSDFFS; 173 1.23 phx } 174 1.23 phx 175 1.23 phx return fstype; 176 1.23 phx } 177 1.23 phx 178 1.23 phx /* 179 1.23 phx * Build a disklabel from APM partitions. 180 1.23 phx * We will just look for a suitable root partition and insert it into 181 1.23 phx * the 'a' slot. Should be sufficient to boot a kernel from it. 182 1.23 phx */ 183 1.23 phx static int 184 1.23 phx search_mac_label(struct of_dev *devp, char *buf, struct disklabel *lp) 185 1.23 phx { 186 1.23 phx struct part_map_entry *pme; 187 1.23 phx struct partition *a_part; 188 1.23 phx size_t nread; 189 1.23 phx int blkno, clust, lastblk, lastclust; 190 1.23 phx u_int8_t fstype; 191 1.23 phx 192 1.23 phx pme = (struct part_map_entry *)buf; 193 1.23 phx a_part = &lp->d_partitions[0]; /* disklabel 'a' partition */ 194 1.23 phx lastclust = -1; 195 1.23 phx 196 1.23 phx for (blkno = lastblk = 1; blkno <= lastblk; blkno++) { 197 1.23 phx if (strategy(devp, F_READ, blkno, DEV_BSIZE, pme, &nread) 198 1.23 phx || nread != DEV_BSIZE) 199 1.23 phx return ERDLAB; 200 1.23 phx if (pme->pmSig != PART_ENTRY_MAGIC || 201 1.23 phx pme->pmPartType[0] == '\0') 202 1.23 phx break; 203 1.23 phx lastblk = pme->pmMapBlkCnt; 204 1.23 phx 205 1.23 phx fstype = check_apm_root(pme, &clust); 206 1.23 phx 207 1.23 phx if (fstype && (lastclust == -1 || clust < lastclust)) { 208 1.23 phx a_part->p_size = pme->pmPartBlkCnt; 209 1.23 phx a_part->p_offset = pme->pmPyPartStart; 210 1.23 phx a_part->p_fstype = fstype; 211 1.23 phx if ((lastclust = clust) == 0) 212 1.23 phx break; /* we won't find a better match */ 213 1.23 phx } 214 1.23 phx } 215 1.23 phx if (lastclust < 0) 216 1.23 phx return ERDLAB; /* no root partition found */ 217 1.23 phx 218 1.23 phx /* pretend we only have partitions 'a', 'b' and 'c' */ 219 1.23 phx lp->d_npartitions = RAW_PART + 1; 220 1.23 phx return 0; 221 1.23 phx } 222 1.23 phx 223 1.1 tsubai static u_long 224 1.14 aymeric get_long(const void *p) 225 1.1 tsubai { 226 1.1 tsubai const unsigned char *cp = p; 227 1.8 tsutsui 228 1.1 tsubai return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24); 229 1.1 tsubai } 230 1.1 tsubai 231 1.1 tsubai /* 232 1.23 phx * Find a valid disklabel from MBR partitions. 233 1.1 tsubai */ 234 1.1 tsubai static int 235 1.23 phx search_dos_label(struct of_dev *devp, u_long off, char *buf, 236 1.23 phx struct disklabel *lp, u_long off0) 237 1.1 tsubai { 238 1.17 uwe size_t nread; 239 1.1 tsubai struct mbr_partition *p; 240 1.1 tsubai int i; 241 1.1 tsubai u_long poff; 242 1.1 tsubai static int recursion; 243 1.8 tsutsui 244 1.17 uwe if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &nread) 245 1.17 uwe || nread != DEV_BSIZE) 246 1.1 tsubai return ERDLAB; 247 1.8 tsutsui 248 1.13 lukem if (*(u_int16_t *)&buf[MBR_MAGIC_OFFSET] != sa_htole16(MBR_MAGIC)) 249 1.1 tsubai return ERDLAB; 250 1.1 tsubai 251 1.1 tsubai if (recursion++ <= 1) 252 1.1 tsubai off0 += off; 253 1.13 lukem for (p = (struct mbr_partition *)(buf + MBR_PART_OFFSET), i = 4; 254 1.1 tsubai --i >= 0; p++) { 255 1.13 lukem if (p->mbrp_type == MBR_PTYPE_NETBSD 256 1.1 tsubai #ifdef COMPAT_386BSD_MBRPART 257 1.13 lukem || (p->mbrp_type == MBR_PTYPE_386BSD && 258 1.1 tsubai (printf("WARNING: old BSD partition ID!\n"), 1) 259 1.1 tsubai /* XXX XXX - libsa printf() is void */ ) 260 1.1 tsubai #endif 261 1.1 tsubai ) { 262 1.2 tsubai poff = get_long(&p->mbrp_start) + off0; 263 1.10 itojun if (strategy(devp, F_READ, poff + 1, 264 1.17 uwe DEV_BSIZE, buf, &nread) == 0 265 1.17 uwe && nread == DEV_BSIZE) { 266 1.1 tsubai if (!getdisklabel(buf, lp)) { 267 1.1 tsubai recursion--; 268 1.1 tsubai return 0; 269 1.1 tsubai } 270 1.1 tsubai } 271 1.17 uwe if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &nread) 272 1.17 uwe || nread != DEV_BSIZE) { 273 1.1 tsubai recursion--; 274 1.1 tsubai return ERDLAB; 275 1.1 tsubai } 276 1.13 lukem } else if (p->mbrp_type == MBR_PTYPE_EXT) { 277 1.2 tsubai poff = get_long(&p->mbrp_start); 278 1.23 phx if (!search_dos_label(devp, poff, buf, lp, off0)) { 279 1.1 tsubai recursion--; 280 1.1 tsubai return 0; 281 1.1 tsubai } 282 1.17 uwe if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &nread) 283 1.17 uwe || nread != DEV_BSIZE) { 284 1.1 tsubai recursion--; 285 1.1 tsubai return ERDLAB; 286 1.1 tsubai } 287 1.1 tsubai } 288 1.1 tsubai } 289 1.1 tsubai recursion--; 290 1.1 tsubai return ERDLAB; 291 1.1 tsubai } 292 1.1 tsubai 293 1.22 tsutsui bool 294 1.22 tsutsui parsefilepath(const char *path, char *devname, char *fname, char *ppart) 295 1.22 tsutsui { 296 1.22 tsutsui char *cp, *lp; 297 1.22 tsutsui char savec; 298 1.22 tsutsui int dhandle; 299 1.22 tsutsui char str[MAXBOOTPATHLEN]; 300 1.22 tsutsui char devtype[16]; 301 1.22 tsutsui 302 1.22 tsutsui DPRINTF("%s: path = %s\n", __func__, path); 303 1.22 tsutsui 304 1.22 tsutsui devtype[0] = '\0'; 305 1.22 tsutsui 306 1.22 tsutsui if (devname != NULL) 307 1.22 tsutsui devname[0] = '\0'; 308 1.22 tsutsui if (fname != NULL) 309 1.22 tsutsui fname[0] = '\0'; 310 1.22 tsutsui if (ppart != NULL) 311 1.22 tsutsui *ppart = 0; 312 1.22 tsutsui 313 1.22 tsutsui strlcpy(str, path, sizeof(str)); 314 1.22 tsutsui lp = str; 315 1.22 tsutsui for (cp = str; *cp != '\0'; lp = cp) { 316 1.22 tsutsui /* For each component of the path name... */ 317 1.22 tsutsui while (*++cp != '\0' && *cp != '/') 318 1.22 tsutsui continue; 319 1.22 tsutsui savec = *cp; 320 1.22 tsutsui *cp = '\0'; 321 1.22 tsutsui /* ...look whether there is a device with this name */ 322 1.22 tsutsui dhandle = OF_finddevice(str); 323 1.22 tsutsui DPRINTF("%s: Checking %s: dhandle = %d\n", 324 1.22 tsutsui __func__, str, dhandle); 325 1.22 tsutsui *cp = savec; 326 1.22 tsutsui if (dhandle != -1) { 327 1.22 tsutsui /* 328 1.30 andvar * If it's a valid device, lp is a delimiter 329 1.22 tsutsui * in the OF device path. 330 1.22 tsutsui */ 331 1.22 tsutsui if (OF_getprop(dhandle, "device_type", devtype, 332 1.22 tsutsui sizeof devtype) < 0) 333 1.22 tsutsui devtype[0] = '\0'; 334 1.22 tsutsui continue; 335 1.22 tsutsui } 336 1.22 tsutsui 337 1.22 tsutsui /* 338 1.22 tsutsui * If not, lp is the delimiter between OF device path 339 1.22 tsutsui * and the specified filename. 340 1.22 tsutsui */ 341 1.22 tsutsui 342 1.22 tsutsui /* Check if the last component was a block device... */ 343 1.22 tsutsui if (strcmp(devtype, "block") == 0) { 344 1.22 tsutsui /* search for arguments */ 345 1.22 tsutsui for (cp = lp; 346 1.22 tsutsui --cp >= str && *cp != '/' && *cp != ':';) 347 1.22 tsutsui continue; 348 1.22 tsutsui if (cp >= str && *cp == ':') { 349 1.22 tsutsui /* found arguments */ 350 1.22 tsutsui for (cp = lp; 351 1.22 tsutsui *--cp != ':' && *cp != ',';) 352 1.22 tsutsui continue; 353 1.22 tsutsui if (*++cp >= 'a' && 354 1.22 tsutsui *cp <= 'a' + MAXPARTITIONS && 355 1.22 tsutsui ppart != NULL) 356 1.22 tsutsui *ppart = *cp; 357 1.22 tsutsui } 358 1.22 tsutsui } 359 1.22 tsutsui if (*lp != '\0') { 360 1.22 tsutsui /* set filename */ 361 1.22 tsutsui DPRINTF("%s: filename = %s\n", __func__, lp); 362 1.22 tsutsui if (fname != NULL) 363 1.22 tsutsui strcpy(fname, lp); 364 1.22 tsutsui if (str != lp) { 365 1.22 tsutsui /* set device path */ 366 1.22 tsutsui *lp = '\0'; 367 1.22 tsutsui DPRINTF("%s: device path = %s\n", 368 1.22 tsutsui __func__, str); 369 1.22 tsutsui if (devname != NULL) 370 1.22 tsutsui strcpy(devname, str); 371 1.22 tsutsui } 372 1.22 tsutsui } 373 1.22 tsutsui return true; 374 1.22 tsutsui } 375 1.22 tsutsui 376 1.22 tsutsui DPRINTF("%s: invalid path?\n", __func__); 377 1.22 tsutsui return false; 378 1.22 tsutsui } 379 1.22 tsutsui 380 1.1 tsubai int 381 1.14 aymeric devopen(struct open_file *of, const char *name, char **file) 382 1.1 tsubai { 383 1.1 tsubai char *cp; 384 1.1 tsubai char partition; 385 1.22 tsutsui char devname[MAXBOOTPATHLEN]; 386 1.22 tsutsui char filename[MAXBOOTPATHLEN]; 387 1.1 tsubai char buf[DEV_BSIZE]; 388 1.1 tsubai struct disklabel label; 389 1.1 tsubai int handle, part; 390 1.17 uwe size_t nread; 391 1.1 tsubai int error = 0; 392 1.28 thorpej uint32_t cells[2]; 393 1.1 tsubai 394 1.1 tsubai if (ofdev.handle != -1) 395 1.1 tsubai panic("devopen"); 396 1.1 tsubai if (of->f_flags != F_READ) 397 1.1 tsubai return EPERM; 398 1.22 tsutsui 399 1.22 tsutsui if (!parsefilepath(name, devname, filename, &partition)) 400 1.22 tsutsui return ENOENT; 401 1.22 tsutsui 402 1.22 tsutsui if (filename[0] == '\0') 403 1.22 tsutsui /* no filename */ 404 1.7 tsubai return ENOENT; 405 1.22 tsutsui 406 1.22 tsutsui if (devname[0] == '\0') 407 1.22 tsutsui /* no device, use default bootdev */ 408 1.22 tsutsui strlcpy(devname, bootdev, sizeof(devname)); 409 1.22 tsutsui 410 1.22 tsutsui DPRINTF("%s: devname = %s, filename = %s\n", 411 1.22 tsutsui __func__, devname, filename); 412 1.22 tsutsui 413 1.22 tsutsui strlcpy(opened_name, devname, sizeof(opened_name)); 414 1.1 tsubai if (partition) { 415 1.1 tsubai cp = opened_name + strlen(opened_name); 416 1.1 tsubai *cp++ = ':'; 417 1.1 tsubai *cp++ = partition; 418 1.1 tsubai *cp = 0; 419 1.1 tsubai } 420 1.22 tsutsui if (filename[0] != '/') 421 1.22 tsutsui strlcat(opened_name, "/", sizeof(opened_name)); 422 1.22 tsutsui strlcat(opened_name, filename, sizeof(opened_name)); 423 1.22 tsutsui 424 1.22 tsutsui DPRINTF("%s: opened_name = %s\n", __func__, opened_name); 425 1.22 tsutsui 426 1.22 tsutsui *file = opened_name + strlen(devname) + 1; 427 1.22 tsutsui if ((handle = OF_finddevice(devname)) == -1) 428 1.1 tsubai return ENOENT; 429 1.1 tsubai if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0) 430 1.1 tsubai return ENXIO; 431 1.23 phx if (!strcmp(buf, "block") && strrchr(devname, ':') == NULL) 432 1.23 phx /* indicate raw partition, when missing */ 433 1.26 tsutsui if (ofw_version >= 3) 434 1.26 tsutsui strlcat(devname, ":0", sizeof(devname)); 435 1.22 tsutsui if ((handle = OF_open(devname)) == -1) 436 1.1 tsubai return ENXIO; 437 1.6 wiz memset(&ofdev, 0, sizeof ofdev); 438 1.1 tsubai ofdev.handle = handle; 439 1.3 tsubai ofdev.dmabuf = NULL; 440 1.28 thorpej cells[0] = MAXPHYS; 441 1.28 thorpej OF_call_method("dma-alloc", handle, 1, 1, (int *)cells); 442 1.29 martin ofdev.dmabuf = (void*)(uintptr_t)cells[1]; 443 1.1 tsubai if (!strcmp(buf, "block")) { 444 1.1 tsubai ofdev.type = OFDEV_DISK; 445 1.1 tsubai ofdev.bsize = DEV_BSIZE; 446 1.23 phx /* First try to find a disklabel without partitions */ 447 1.27 tsutsui if (!floppyboot && 448 1.27 tsutsui (strategy(&ofdev, F_READ, 449 1.27 tsutsui LABELSECTOR, DEV_BSIZE, buf, &nread) != 0 450 1.27 tsutsui || nread != DEV_BSIZE 451 1.27 tsutsui || getdisklabel(buf, &label))) { 452 1.23 phx /* Else try APM or MBR partitions */ 453 1.24 mrg struct drvr_map *map = (struct drvr_map *)buf; 454 1.24 mrg 455 1.24 mrg if (map->sbSig == DRIVER_MAP_MAGIC) 456 1.23 phx error = search_mac_label(&ofdev, buf, &label); 457 1.23 phx else 458 1.23 phx error = search_dos_label(&ofdev, 0, buf, 459 1.23 phx &label, 0); 460 1.1 tsubai if (error && error != ERDLAB) 461 1.1 tsubai goto bad; 462 1.1 tsubai } 463 1.1 tsubai 464 1.1 tsubai if (error == ERDLAB) { 465 1.1 tsubai if (partition) 466 1.8 tsutsui /* 467 1.31 andvar * User specified a partition, 468 1.8 tsutsui * but there is none 469 1.8 tsutsui */ 470 1.1 tsubai goto bad; 471 1.23 phx /* No label, just use complete disk */ 472 1.1 tsubai ofdev.partoff = 0; 473 1.1 tsubai } else { 474 1.1 tsubai part = partition ? partition - 'a' : 0; 475 1.1 tsubai ofdev.partoff = label.d_partitions[part].p_offset; 476 1.1 tsubai } 477 1.8 tsutsui 478 1.19 mrg of->f_dev = of_devsw; 479 1.1 tsubai of->f_devdata = &ofdev; 480 1.20 hauke file_system[0] = file_system_ffsv1; 481 1.20 hauke file_system[1] = file_system_ffsv2; 482 1.20 hauke file_system[2] = file_system_lfsv1; 483 1.20 hauke file_system[3] = file_system_lfsv2; 484 1.20 hauke file_system[4] = file_system_ustarfs; 485 1.20 hauke file_system[5] = file_system_cd9660; 486 1.20 hauke file_system[6] = file_system_hfs; 487 1.25 matt file_system[7] = file_system_dosfs; 488 1.25 matt nfsys = 8; 489 1.1 tsubai return 0; 490 1.1 tsubai } 491 1.1 tsubai if (!strcmp(buf, "network")) { 492 1.1 tsubai ofdev.type = OFDEV_NET; 493 1.19 mrg of->f_dev = of_devsw; 494 1.1 tsubai of->f_devdata = &ofdev; 495 1.5 tsubai file_system[0] = file_system_nfs; 496 1.1 tsubai nfsys = 1; 497 1.17 uwe if ((error = net_open(&ofdev))) 498 1.1 tsubai goto bad; 499 1.1 tsubai return 0; 500 1.1 tsubai } 501 1.1 tsubai error = EFTYPE; 502 1.1 tsubai bad: 503 1.1 tsubai OF_close(handle); 504 1.1 tsubai ofdev.handle = -1; 505 1.1 tsubai return error; 506 1.1 tsubai } 507