int bios_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { bios_diskinfo_t *pdi; extern dev_t bootdev; int biosdev; /* all sysctl names at this level except diskinfo are terminal */ if (namelen != 1 && name[0] != BIOS_DISKINFO) return (ENOTDIR); /* overloaded */ if (!(bootapiver & BAPIV_VECTOR)) return EOPNOTSUPP; switch (name[0]) { case BIOS_DEV: if ((pdi = bios_getdiskinfo(bootdev)) == NULL) return ENXIO; biosdev = pdi->bios_number; return sysctl_rdint(oldp, oldlenp, newp, biosdev); case BIOS_DISKINFO: if (namelen != 2) return ENOTDIR; if ((pdi = bios_getdiskinfo(name[1])) == NULL) return ENXIO; return sysctl_rdstruct(oldp, oldlenp, newp, pdi, sizeof(*pdi)); case BIOS_CKSUMLEN: return sysctl_rdint(oldp, oldlenp, newp, bios_cksumlen); default: return EOPNOTSUPP; } /* NOTREACHED */ }
/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. * * If dos partition table requested, attempt to load it and * find disklabel inside a DOS partition. * * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but * we cannot because it doesn't always exist. So.. we assume the * MBR is valid. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { bios_diskinfo_t *pdi; struct buf *bp = NULL; dev_t devno; int error; if ((error = initdisklabel(lp))) goto done; /* Look for any BIOS geometry information we should honour. */ devno = chrtoblk(dev); if (devno == NODEV) devno = dev; pdi = bios_getdiskinfo(MAKEBOOTDEV(major(devno), 0, 0, DISKUNIT(devno), RAW_PART)); if (pdi != NULL && pdi->bios_heads > 0 && pdi->bios_sectors > 0) { #ifdef DEBUG printf("Disk GEOM %u/%u/%u -> BIOS GEOM %u/%u/%u\n", lp->d_ntracks, lp->d_nsectors, lp->d_ncylinders, pdi->bios_heads, pdi->bios_sectors, DL_GETDSIZE(lp) / (pdi->bios_heads * pdi->bios_sectors)); #endif lp->d_ntracks = pdi->bios_heads; lp->d_nsectors = pdi->bios_sectors; lp->d_secpercyl = pdi->bios_sectors * pdi->bios_heads; lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; } /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
/* Probe for all BIOS floppies */ static void floppyprobe(void) { struct diskinfo *dip; int i; /* Floppies */ for(i = 0; i < 4; i++) { dip = alloc(sizeof(struct diskinfo)); bzero(dip, sizeof(*dip)); if(bios_getdiskinfo(i, &dip->bios_info)) { #ifdef BIOS_DEBUG if (debug) printf(" <!fd%u>", i); #endif free(dip, 0); break; } printf(" fd%u", i); /* Fill out best we can - (fd?) */ dip->bios_info.bsd_dev = MAKEBOOTDEV(2, 0, 0, i, RAW_PART); /* * Delay reading the disklabel until we're sure we want * to boot from the floppy. Doing this avoids a delay * (sometimes very long) when trying to read the label * and the drive is unplugged. */ dip->bios_info.flags |= BDI_BADLABEL; /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); } }
/* Probe for all BIOS hard disks */ static void hardprobe(void) { struct diskinfo *dip; int i; u_int bsdunit, type; u_int scsi = 0, ide = 0; const char *dc = (const char *)((0x40 << 4) + 0x75); /* Hard disks */ for (i = 0x80; i < (0x80 + *dc); i++) { dip = alloc(sizeof(struct diskinfo)); bzero(dip, sizeof(*dip)); if(bios_getdiskinfo(i, &dip->bios_info)) { #ifdef BIOS_DEBUG if (debug) printf(" <!hd%u>", i&0x7f); #endif free(dip, 0); break; } printf(" hd%u%s", i&0x7f, (dip->bios_info.bios_edd > 0?"+":"")); /* Try to find the label, to figure out device type */ if((bios_getdisklabel(&dip->bios_info, &dip->disklabel)) ) { printf("*"); bsdunit = ide++; type = 0; /* XXX let it be IDE */ } else { /* Best guess */ switch (dip->disklabel.d_type) { case DTYPE_SCSI: type = 4; bsdunit = scsi++; dip->bios_info.flags |= BDI_GOODLABEL; break; case DTYPE_ESDI: case DTYPE_ST506: type = 0; bsdunit = ide++; dip->bios_info.flags |= BDI_GOODLABEL; break; default: dip->bios_info.flags |= BDI_BADLABEL; type = 0; /* XXX Suggest IDE */ bsdunit = ide++; } } dip->bios_info.checksum = 0; /* just in case */ /* Fill out best we can */ dip->bios_info.bsd_dev = MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART); /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); } }
void cdprobe(void) { struct diskinfo *dip; int cddev = bios_cddev & 0xff; /* Another BIOS boot device... */ if (bios_cddev == -1) /* Not been set, so don't use */ return; dip = alloc(sizeof(struct diskinfo)); bzero(dip, sizeof(*dip)); #if 0 if (bios_getdiskinfo(cddev, &dip->bios_info)) { printf(" <!cd0>"); /* XXX */ free(dip, 0); return; } #endif printf(" cd0"); dip->bios_info.bios_number = cddev; dip->bios_info.bios_edd = 1; /* Use the LBA calls */ dip->bios_info.flags |= BDI_GOODLABEL | BDI_EL_TORITO; dip->bios_info.checksum = 0; /* just in case */ dip->bios_info.bsd_dev = MAKEBOOTDEV(6, 0, 0, 0, RAW_PART); /* Create an imaginary disk label */ dip->disklabel.d_secsize = 2048; dip->disklabel.d_ntracks = 1; dip->disklabel.d_nsectors = 100; dip->disklabel.d_ncylinders = 1; dip->disklabel.d_secpercyl = dip->disklabel.d_ntracks * dip->disklabel.d_nsectors; if (dip->disklabel.d_secpercyl == 0) { dip->disklabel.d_secpercyl = 100; /* as long as it's not 0, since readdisklabel divides by it */ } strncpy(dip->disklabel.d_typename, "ATAPI CD-ROM", sizeof(dip->disklabel.d_typename)); dip->disklabel.d_type = DTYPE_ATAPI; strncpy(dip->disklabel.d_packname, "fictitious", sizeof(dip->disklabel.d_packname)); dip->disklabel.d_secperunit = 100; dip->disklabel.d_bbsize = 2048; dip->disklabel.d_sbsize = 2048; /* 'a' partition covering the "whole" disk */ dip->disklabel.d_partitions[0].p_offset = 0; dip->disklabel.d_partitions[0].p_size = 100; dip->disklabel.d_partitions[0].p_fstype = FS_UNUSED; /* The raw partition is special */ dip->disklabel.d_partitions[RAW_PART].p_offset = 0; dip->disklabel.d_partitions[RAW_PART].p_size = 100; dip->disklabel.d_partitions[RAW_PART].p_fstype = FS_UNUSED; dip->disklabel.d_npartitions = MAXPARTITIONS; dip->disklabel.d_magic = DISKMAGIC; dip->disklabel.d_magic2 = DISKMAGIC; dip->disklabel.d_checksum = dkcksum(&dip->disklabel); /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); }