1*f14fb602SLionel Sambuc /* $NetBSD: biosdisk.c,v 1.42 2012/07/03 15:24:37 tsutsui Exp $ */ 258a2b000SEvgeniy Ivanov 358a2b000SEvgeniy Ivanov /* 458a2b000SEvgeniy Ivanov * Copyright (c) 1996, 1998 558a2b000SEvgeniy Ivanov * Matthias Drochner. All rights reserved. 658a2b000SEvgeniy Ivanov * 758a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 858a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 958a2b000SEvgeniy Ivanov * are met: 1058a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 1158a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 1258a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 1358a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 1458a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 1558a2b000SEvgeniy Ivanov * 1658a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1758a2b000SEvgeniy Ivanov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1858a2b000SEvgeniy Ivanov * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1958a2b000SEvgeniy Ivanov * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2058a2b000SEvgeniy Ivanov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2158a2b000SEvgeniy Ivanov * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2258a2b000SEvgeniy Ivanov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2358a2b000SEvgeniy Ivanov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2458a2b000SEvgeniy Ivanov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2558a2b000SEvgeniy Ivanov * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2658a2b000SEvgeniy Ivanov * 2758a2b000SEvgeniy Ivanov */ 2858a2b000SEvgeniy Ivanov 2958a2b000SEvgeniy Ivanov /* 3058a2b000SEvgeniy Ivanov * raw BIOS disk device for libsa. 3158a2b000SEvgeniy Ivanov * needs lowlevel parts from bios_disk.S and biosdisk_ll.c 3258a2b000SEvgeniy Ivanov * partly from netbsd:sys/arch/i386/boot/disk.c 3358a2b000SEvgeniy Ivanov * no bad144 handling! 3458a2b000SEvgeniy Ivanov * 3558a2b000SEvgeniy Ivanov * A lot of this must match sys/kern/subr_disk_mbr.c 3658a2b000SEvgeniy Ivanov */ 3758a2b000SEvgeniy Ivanov 3858a2b000SEvgeniy Ivanov /* 3958a2b000SEvgeniy Ivanov * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 4058a2b000SEvgeniy Ivanov * 4158a2b000SEvgeniy Ivanov * Mach Operating System 4258a2b000SEvgeniy Ivanov * Copyright (c) 1992, 1991 Carnegie Mellon University 4358a2b000SEvgeniy Ivanov * All Rights Reserved. 4458a2b000SEvgeniy Ivanov * 4558a2b000SEvgeniy Ivanov * Permission to use, copy, modify and distribute this software and its 4658a2b000SEvgeniy Ivanov * documentation is hereby granted, provided that both the copyright 4758a2b000SEvgeniy Ivanov * notice and this permission notice appear in all copies of the 4858a2b000SEvgeniy Ivanov * software, derivative works or modified versions, and any portions 4958a2b000SEvgeniy Ivanov * thereof, and that both notices appear in supporting documentation. 5058a2b000SEvgeniy Ivanov * 5158a2b000SEvgeniy Ivanov * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 5258a2b000SEvgeniy Ivanov * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 5358a2b000SEvgeniy Ivanov * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 5458a2b000SEvgeniy Ivanov * 5558a2b000SEvgeniy Ivanov * Carnegie Mellon requests users of this software to return to 5658a2b000SEvgeniy Ivanov * 5758a2b000SEvgeniy Ivanov * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 5858a2b000SEvgeniy Ivanov * School of Computer Science 5958a2b000SEvgeniy Ivanov * Carnegie Mellon University 6058a2b000SEvgeniy Ivanov * Pittsburgh PA 15213-3890 6158a2b000SEvgeniy Ivanov * 6258a2b000SEvgeniy Ivanov * any improvements or extensions that they make and grant Carnegie Mellon 6358a2b000SEvgeniy Ivanov * the rights to redistribute these changes. 6458a2b000SEvgeniy Ivanov */ 6558a2b000SEvgeniy Ivanov 6658a2b000SEvgeniy Ivanov #if !defined(NO_DISKLABEL) || !defined(NO_GPT) 6758a2b000SEvgeniy Ivanov #define FSTYPENAMES 6858a2b000SEvgeniy Ivanov #endif 6958a2b000SEvgeniy Ivanov 7058a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h> 7158a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h> 7258a2b000SEvgeniy Ivanov 7358a2b000SEvgeniy Ivanov #include <sys/types.h> 7458a2b000SEvgeniy Ivanov #include <sys/md5.h> 7558a2b000SEvgeniy Ivanov #include <sys/param.h> 7658a2b000SEvgeniy Ivanov #include <sys/disklabel.h> 7758a2b000SEvgeniy Ivanov #include <sys/disklabel_gpt.h> 7858a2b000SEvgeniy Ivanov #include <sys/uuid.h> 7958a2b000SEvgeniy Ivanov 8058a2b000SEvgeniy Ivanov #include <fs/cd9660/iso.h> 8158a2b000SEvgeniy Ivanov 8258a2b000SEvgeniy Ivanov #include <lib/libsa/saerrno.h> 8358a2b000SEvgeniy Ivanov #include <machine/cpu.h> 8458a2b000SEvgeniy Ivanov 8558a2b000SEvgeniy Ivanov #include "libi386.h" 8658a2b000SEvgeniy Ivanov #include "biosdisk_ll.h" 8758a2b000SEvgeniy Ivanov #include "biosdisk.h" 8858a2b000SEvgeniy Ivanov #ifdef _STANDALONE 8958a2b000SEvgeniy Ivanov #include "bootinfo.h" 9058a2b000SEvgeniy Ivanov #endif 9158a2b000SEvgeniy Ivanov 9258a2b000SEvgeniy Ivanov #define BUFSIZE 2048 /* must be large enough for a CD sector */ 9358a2b000SEvgeniy Ivanov 9458a2b000SEvgeniy Ivanov #define BIOSDISKNPART 26 9558a2b000SEvgeniy Ivanov 9658a2b000SEvgeniy Ivanov struct biosdisk { 9758a2b000SEvgeniy Ivanov struct biosdisk_ll ll; 9858a2b000SEvgeniy Ivanov daddr_t boff; 9958a2b000SEvgeniy Ivanov char buf[BUFSIZE]; 10058a2b000SEvgeniy Ivanov #if !defined(NO_DISKLABEL) || !defined(NO_GPT) 10158a2b000SEvgeniy Ivanov struct { 10258a2b000SEvgeniy Ivanov daddr_t offset; 10358a2b000SEvgeniy Ivanov daddr_t size; 10458a2b000SEvgeniy Ivanov int fstype; 10558a2b000SEvgeniy Ivanov } part[BIOSDISKNPART]; 10658a2b000SEvgeniy Ivanov #endif 10758a2b000SEvgeniy Ivanov }; 10858a2b000SEvgeniy Ivanov 10958a2b000SEvgeniy Ivanov #ifndef NO_GPT 11058a2b000SEvgeniy Ivanov const struct uuid GET_nbsd_raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME; 11158a2b000SEvgeniy Ivanov const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS; 11258a2b000SEvgeniy Ivanov const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS; 11358a2b000SEvgeniy Ivanov const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; 11458a2b000SEvgeniy Ivanov #endif /* NO_GPT */ 11558a2b000SEvgeniy Ivanov 11658a2b000SEvgeniy Ivanov #ifdef _STANDALONE 11758a2b000SEvgeniy Ivanov static struct btinfo_bootdisk bi_disk; 11858a2b000SEvgeniy Ivanov static struct btinfo_bootwedge bi_wedge; 11958a2b000SEvgeniy Ivanov #endif 12058a2b000SEvgeniy Ivanov 12158a2b000SEvgeniy Ivanov #define RF_PROTECTED_SECTORS 64 /* XXX refer to <.../rf_optnames.h> */ 12258a2b000SEvgeniy Ivanov 12358a2b000SEvgeniy Ivanov int 12458a2b000SEvgeniy Ivanov biosdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 12558a2b000SEvgeniy Ivanov void *buf, size_t *rsize) 12658a2b000SEvgeniy Ivanov { 12758a2b000SEvgeniy Ivanov struct biosdisk *d; 12858a2b000SEvgeniy Ivanov int blks, frag; 12958a2b000SEvgeniy Ivanov 13058a2b000SEvgeniy Ivanov if (flag != F_READ) 13158a2b000SEvgeniy Ivanov return EROFS; 13258a2b000SEvgeniy Ivanov 13358a2b000SEvgeniy Ivanov d = (struct biosdisk *) devdata; 13458a2b000SEvgeniy Ivanov 13558a2b000SEvgeniy Ivanov if (d->ll.type == BIOSDISK_TYPE_CD) 13658a2b000SEvgeniy Ivanov dblk = dblk * DEV_BSIZE / ISO_DEFAULT_BLOCK_SIZE; 13758a2b000SEvgeniy Ivanov 13858a2b000SEvgeniy Ivanov dblk += d->boff; 13958a2b000SEvgeniy Ivanov 14058a2b000SEvgeniy Ivanov blks = size / d->ll.secsize; 14158a2b000SEvgeniy Ivanov if (blks && readsects(&d->ll, dblk, blks, buf, 0)) { 14258a2b000SEvgeniy Ivanov if (rsize) 14358a2b000SEvgeniy Ivanov *rsize = 0; 14458a2b000SEvgeniy Ivanov return EIO; 14558a2b000SEvgeniy Ivanov } 14658a2b000SEvgeniy Ivanov 14758a2b000SEvgeniy Ivanov /* needed for CD */ 14858a2b000SEvgeniy Ivanov frag = size % d->ll.secsize; 14958a2b000SEvgeniy Ivanov if (frag) { 15058a2b000SEvgeniy Ivanov if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) { 15158a2b000SEvgeniy Ivanov if (rsize) 15258a2b000SEvgeniy Ivanov *rsize = blks * d->ll.secsize; 15358a2b000SEvgeniy Ivanov return EIO; 15458a2b000SEvgeniy Ivanov } 15558a2b000SEvgeniy Ivanov memcpy(buf + blks * d->ll.secsize, d->buf, frag); 15658a2b000SEvgeniy Ivanov } 15758a2b000SEvgeniy Ivanov 15858a2b000SEvgeniy Ivanov if (rsize) 15958a2b000SEvgeniy Ivanov *rsize = size; 16058a2b000SEvgeniy Ivanov return 0; 16158a2b000SEvgeniy Ivanov } 16258a2b000SEvgeniy Ivanov 16358a2b000SEvgeniy Ivanov static struct biosdisk * 16458a2b000SEvgeniy Ivanov alloc_biosdisk(int biosdev) 16558a2b000SEvgeniy Ivanov { 16658a2b000SEvgeniy Ivanov struct biosdisk *d; 16758a2b000SEvgeniy Ivanov 16858a2b000SEvgeniy Ivanov d = alloc(sizeof(*d)); 16958a2b000SEvgeniy Ivanov if (d == NULL) 17058a2b000SEvgeniy Ivanov return NULL; 17158a2b000SEvgeniy Ivanov memset(d, 0, sizeof(*d)); 17258a2b000SEvgeniy Ivanov 17358a2b000SEvgeniy Ivanov d->ll.dev = biosdev; 17458a2b000SEvgeniy Ivanov if (set_geometry(&d->ll, NULL)) { 17558a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 17658a2b000SEvgeniy Ivanov printf("no geometry information\n"); 17758a2b000SEvgeniy Ivanov #endif 17858a2b000SEvgeniy Ivanov dealloc(d, sizeof(*d)); 17958a2b000SEvgeniy Ivanov return NULL; 18058a2b000SEvgeniy Ivanov } 18158a2b000SEvgeniy Ivanov return d; 18258a2b000SEvgeniy Ivanov } 18358a2b000SEvgeniy Ivanov 18458a2b000SEvgeniy Ivanov #if !defined(NO_DISKLABEL) || !defined(NO_GPT) 18558a2b000SEvgeniy Ivanov static void 18658a2b000SEvgeniy Ivanov md5(void *hash, const void *data, size_t len) 18758a2b000SEvgeniy Ivanov { 18858a2b000SEvgeniy Ivanov MD5_CTX ctx; 18958a2b000SEvgeniy Ivanov 19058a2b000SEvgeniy Ivanov MD5Init(&ctx); 19158a2b000SEvgeniy Ivanov MD5Update(&ctx, data, len); 19258a2b000SEvgeniy Ivanov MD5Final(hash, &ctx); 19358a2b000SEvgeniy Ivanov 19458a2b000SEvgeniy Ivanov return; 19558a2b000SEvgeniy Ivanov } 19658a2b000SEvgeniy Ivanov #endif 19758a2b000SEvgeniy Ivanov 19858a2b000SEvgeniy Ivanov #ifndef NO_GPT 19958a2b000SEvgeniy Ivanov static bool 20058a2b000SEvgeniy Ivanov guid_is_nil(const struct uuid *u) 20158a2b000SEvgeniy Ivanov { 20258a2b000SEvgeniy Ivanov static const struct uuid nil = { .time_low = 0 }; 20358a2b000SEvgeniy Ivanov return (memcmp(u, &nil, sizeof(*u)) == 0 ? true : false); 20458a2b000SEvgeniy Ivanov } 20558a2b000SEvgeniy Ivanov 20658a2b000SEvgeniy Ivanov static bool 20758a2b000SEvgeniy Ivanov guid_is_equal(const struct uuid *a, const struct uuid *b) 20858a2b000SEvgeniy Ivanov { 20958a2b000SEvgeniy Ivanov return (memcmp(a, b, sizeof(*a)) == 0 ? true : false); 21058a2b000SEvgeniy Ivanov } 21158a2b000SEvgeniy Ivanov 21258a2b000SEvgeniy Ivanov static int 21358a2b000SEvgeniy Ivanov check_gpt(struct biosdisk *d, daddr_t sector) 21458a2b000SEvgeniy Ivanov { 21558a2b000SEvgeniy Ivanov struct gpt_hdr gpth; 21658a2b000SEvgeniy Ivanov const struct gpt_ent *ep; 21758a2b000SEvgeniy Ivanov const struct uuid *u; 21858a2b000SEvgeniy Ivanov daddr_t entblk; 21958a2b000SEvgeniy Ivanov size_t size; 22058a2b000SEvgeniy Ivanov uint32_t crc; 22158a2b000SEvgeniy Ivanov int sectors; 22258a2b000SEvgeniy Ivanov int entries; 22358a2b000SEvgeniy Ivanov int entry; 22458a2b000SEvgeniy Ivanov int i, j; 22558a2b000SEvgeniy Ivanov 22658a2b000SEvgeniy Ivanov /* read in gpt_hdr sector */ 22758a2b000SEvgeniy Ivanov if (readsects(&d->ll, sector, 1, d->buf, 1)) { 22858a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 22958a2b000SEvgeniy Ivanov printf("Error reading GPT header at %"PRId64"\n", sector); 23058a2b000SEvgeniy Ivanov #endif 23158a2b000SEvgeniy Ivanov return EIO; 23258a2b000SEvgeniy Ivanov } 23358a2b000SEvgeniy Ivanov 23458a2b000SEvgeniy Ivanov gpth = *(const struct gpt_hdr *)d->buf; 23558a2b000SEvgeniy Ivanov 23658a2b000SEvgeniy Ivanov if (memcmp(GPT_HDR_SIG, gpth.hdr_sig, sizeof(gpth.hdr_sig))) 23758a2b000SEvgeniy Ivanov return -1; 23858a2b000SEvgeniy Ivanov 23958a2b000SEvgeniy Ivanov crc = gpth.hdr_crc_self; 24058a2b000SEvgeniy Ivanov gpth.hdr_crc_self = 0; 24158a2b000SEvgeniy Ivanov gpth.hdr_crc_self = crc32(0, (const void *)&gpth, GPT_HDR_SIZE); 24258a2b000SEvgeniy Ivanov if (gpth.hdr_crc_self != crc) { 24358a2b000SEvgeniy Ivanov return -1; 24458a2b000SEvgeniy Ivanov } 24558a2b000SEvgeniy Ivanov 24658a2b000SEvgeniy Ivanov if (gpth.hdr_lba_self != sector) 24758a2b000SEvgeniy Ivanov return -1; 24858a2b000SEvgeniy Ivanov 24958a2b000SEvgeniy Ivanov #ifdef _STANDALONE 25058a2b000SEvgeniy Ivanov bi_wedge.matchblk = sector; 25158a2b000SEvgeniy Ivanov bi_wedge.matchnblks = 1; 25258a2b000SEvgeniy Ivanov 25358a2b000SEvgeniy Ivanov md5(bi_wedge.matchhash, d->buf, d->ll.secsize); 25458a2b000SEvgeniy Ivanov #endif 25558a2b000SEvgeniy Ivanov 25658a2b000SEvgeniy Ivanov sectors = sizeof(d->buf)/d->ll.secsize; /* sectors per buffer */ 25758a2b000SEvgeniy Ivanov entries = sizeof(d->buf)/gpth.hdr_entsz; /* entries per buffer */ 25858a2b000SEvgeniy Ivanov entblk = gpth.hdr_lba_table; 25958a2b000SEvgeniy Ivanov crc = crc32(0, NULL, 0); 26058a2b000SEvgeniy Ivanov 26158a2b000SEvgeniy Ivanov j = 0; 26258a2b000SEvgeniy Ivanov ep = (const struct gpt_ent *)d->buf; 26358a2b000SEvgeniy Ivanov 26458a2b000SEvgeniy Ivanov for (entry = 0; entry < gpth.hdr_entries; entry += entries) { 26558a2b000SEvgeniy Ivanov size = MIN(sizeof(d->buf), 26658a2b000SEvgeniy Ivanov (gpth.hdr_entries - entry) * gpth.hdr_entsz); 26758a2b000SEvgeniy Ivanov entries = size / gpth.hdr_entsz; 26858a2b000SEvgeniy Ivanov sectors = roundup(size, d->ll.secsize) / d->ll.secsize; 26958a2b000SEvgeniy Ivanov if (readsects(&d->ll, entblk, sectors, d->buf, 1)) 27058a2b000SEvgeniy Ivanov return -1; 27158a2b000SEvgeniy Ivanov entblk += sectors; 27258a2b000SEvgeniy Ivanov crc = crc32(crc, (const void *)d->buf, size); 27358a2b000SEvgeniy Ivanov 27458a2b000SEvgeniy Ivanov for (i = 0; j < BIOSDISKNPART && i < entries; i++, j++) { 27558a2b000SEvgeniy Ivanov u = (const struct uuid *)ep[i].ent_type; 27658a2b000SEvgeniy Ivanov if (!guid_is_nil(u)) { 27758a2b000SEvgeniy Ivanov d->part[j].offset = ep[i].ent_lba_start; 27858a2b000SEvgeniy Ivanov d->part[j].size = ep[i].ent_lba_end - 27958a2b000SEvgeniy Ivanov ep[i].ent_lba_start + 1; 28058a2b000SEvgeniy Ivanov if (guid_is_equal(u, &GET_nbsd_ffs)) 28158a2b000SEvgeniy Ivanov d->part[j].fstype = FS_BSDFFS; 28258a2b000SEvgeniy Ivanov else if (guid_is_equal(u, &GET_nbsd_lfs)) 28358a2b000SEvgeniy Ivanov d->part[j].fstype = FS_BSDLFS; 28458a2b000SEvgeniy Ivanov else if (guid_is_equal(u, &GET_nbsd_raid)) 28558a2b000SEvgeniy Ivanov d->part[j].fstype = FS_RAID; 28658a2b000SEvgeniy Ivanov else if (guid_is_equal(u, &GET_nbsd_swap)) 28758a2b000SEvgeniy Ivanov d->part[j].fstype = FS_SWAP; 28858a2b000SEvgeniy Ivanov else 28958a2b000SEvgeniy Ivanov d->part[j].fstype = FS_OTHER; 29058a2b000SEvgeniy Ivanov } 29158a2b000SEvgeniy Ivanov } 29258a2b000SEvgeniy Ivanov 29358a2b000SEvgeniy Ivanov } 29458a2b000SEvgeniy Ivanov 29558a2b000SEvgeniy Ivanov if (crc != gpth.hdr_crc_table) { 29658a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 29758a2b000SEvgeniy Ivanov printf("GPT table CRC invalid\n"); 29858a2b000SEvgeniy Ivanov #endif 29958a2b000SEvgeniy Ivanov return -1; 30058a2b000SEvgeniy Ivanov } 30158a2b000SEvgeniy Ivanov 30258a2b000SEvgeniy Ivanov return 0; 30358a2b000SEvgeniy Ivanov } 30458a2b000SEvgeniy Ivanov 30558a2b000SEvgeniy Ivanov static int 30658a2b000SEvgeniy Ivanov read_gpt(struct biosdisk *d) 30758a2b000SEvgeniy Ivanov { 30858a2b000SEvgeniy Ivanov struct biosdisk_extinfo ed; 30958a2b000SEvgeniy Ivanov daddr_t gptsector[2]; 31058a2b000SEvgeniy Ivanov int i, error; 31158a2b000SEvgeniy Ivanov 31258a2b000SEvgeniy Ivanov if (d->ll.type != BIOSDISK_TYPE_HD) 31358a2b000SEvgeniy Ivanov /* No GPT on floppy and CD */ 31458a2b000SEvgeniy Ivanov return -1; 31558a2b000SEvgeniy Ivanov 31658a2b000SEvgeniy Ivanov gptsector[0] = GPT_HDR_BLKNO; 31758a2b000SEvgeniy Ivanov if (set_geometry(&d->ll, &ed) == 0 && d->ll.flags & BIOSDISK_INT13EXT) { 31858a2b000SEvgeniy Ivanov gptsector[1] = ed.totsec - 1; 319*f14fb602SLionel Sambuc /* Sanity check values returned from BIOS */ 320*f14fb602SLionel Sambuc if (ed.sbytes >= 512 && (ed.sbytes & (ed.sbytes - 1)) == 0) 32158a2b000SEvgeniy Ivanov d->ll.secsize = ed.sbytes; 32258a2b000SEvgeniy Ivanov } else { 32358a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 32458a2b000SEvgeniy Ivanov printf("Unable to determine extended disk geometry - " 32558a2b000SEvgeniy Ivanov "using CHS\n"); 32658a2b000SEvgeniy Ivanov #endif 32758a2b000SEvgeniy Ivanov /* at least try some other reasonable values then */ 32858a2b000SEvgeniy Ivanov gptsector[1] = d->ll.chs_sectors - 1; 32958a2b000SEvgeniy Ivanov } 33058a2b000SEvgeniy Ivanov 33158a2b000SEvgeniy Ivanov /* 33258a2b000SEvgeniy Ivanov * Use any valid GPT available, do not require both GPTs to be valid 33358a2b000SEvgeniy Ivanov */ 33458a2b000SEvgeniy Ivanov for (i = 0; i < __arraycount(gptsector); i++) { 33558a2b000SEvgeniy Ivanov error = check_gpt(d, gptsector[i]); 33658a2b000SEvgeniy Ivanov if (error == 0) 33758a2b000SEvgeniy Ivanov break; 33858a2b000SEvgeniy Ivanov } 33958a2b000SEvgeniy Ivanov 34058a2b000SEvgeniy Ivanov if (i >= __arraycount(gptsector)) { 34158a2b000SEvgeniy Ivanov memset(d->part, 0, sizeof(d->part)); 34258a2b000SEvgeniy Ivanov return -1; 34358a2b000SEvgeniy Ivanov } 34458a2b000SEvgeniy Ivanov 34558a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 34658a2b000SEvgeniy Ivanov printf("using %s GPT\n", (i == 0) ? "primary" : "secondary"); 34758a2b000SEvgeniy Ivanov #endif 34858a2b000SEvgeniy Ivanov return 0; 34958a2b000SEvgeniy Ivanov } 35058a2b000SEvgeniy Ivanov #endif /* !NO_GPT */ 35158a2b000SEvgeniy Ivanov 35258a2b000SEvgeniy Ivanov #ifndef NO_DISKLABEL 35358a2b000SEvgeniy Ivanov static void 35458a2b000SEvgeniy Ivanov ingest_label(struct biosdisk *d, struct disklabel *lp) 35558a2b000SEvgeniy Ivanov { 35658a2b000SEvgeniy Ivanov int part; 35758a2b000SEvgeniy Ivanov 35858a2b000SEvgeniy Ivanov memset(d->part, 0, sizeof(d->part)); 35958a2b000SEvgeniy Ivanov 36058a2b000SEvgeniy Ivanov for (part = 0; part < lp->d_npartitions; part++) { 36158a2b000SEvgeniy Ivanov if (lp->d_partitions[part].p_size == 0) 36258a2b000SEvgeniy Ivanov continue; 36358a2b000SEvgeniy Ivanov if (lp->d_partitions[part].p_fstype == FS_UNUSED) 36458a2b000SEvgeniy Ivanov continue; 36558a2b000SEvgeniy Ivanov d->part[part].fstype = lp->d_partitions[part].p_fstype; 36658a2b000SEvgeniy Ivanov d->part[part].offset = lp->d_partitions[part].p_offset; 36758a2b000SEvgeniy Ivanov d->part[part].size = lp->d_partitions[part].p_size; 36858a2b000SEvgeniy Ivanov } 36958a2b000SEvgeniy Ivanov } 37058a2b000SEvgeniy Ivanov 37158a2b000SEvgeniy Ivanov static int 37258a2b000SEvgeniy Ivanov check_label(struct biosdisk *d, daddr_t sector) 37358a2b000SEvgeniy Ivanov { 37458a2b000SEvgeniy Ivanov struct disklabel *lp; 37558a2b000SEvgeniy Ivanov 37658a2b000SEvgeniy Ivanov /* find partition in NetBSD disklabel */ 37758a2b000SEvgeniy Ivanov if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) { 37858a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 37958a2b000SEvgeniy Ivanov printf("Error reading disklabel\n"); 38058a2b000SEvgeniy Ivanov #endif 38158a2b000SEvgeniy Ivanov return EIO; 38258a2b000SEvgeniy Ivanov } 38358a2b000SEvgeniy Ivanov lp = (struct disklabel *) (d->buf + LABELOFFSET); 38458a2b000SEvgeniy Ivanov if (lp->d_magic != DISKMAGIC || dkcksum(lp)) { 38558a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 38658a2b000SEvgeniy Ivanov printf("warning: no disklabel in sector %"PRId64"\n", sector); 38758a2b000SEvgeniy Ivanov #endif 38858a2b000SEvgeniy Ivanov return -1; 38958a2b000SEvgeniy Ivanov } 39058a2b000SEvgeniy Ivanov 39158a2b000SEvgeniy Ivanov ingest_label(d, lp); 39258a2b000SEvgeniy Ivanov 39358a2b000SEvgeniy Ivanov #ifdef _STANDALONE 39458a2b000SEvgeniy Ivanov bi_disk.labelsector = sector + LABELSECTOR; 39558a2b000SEvgeniy Ivanov bi_disk.label.type = lp->d_type; 39658a2b000SEvgeniy Ivanov memcpy(bi_disk.label.packname, lp->d_packname, 16); 39758a2b000SEvgeniy Ivanov bi_disk.label.checksum = lp->d_checksum; 39858a2b000SEvgeniy Ivanov 39958a2b000SEvgeniy Ivanov bi_wedge.matchblk = sector + LABELSECTOR; 40058a2b000SEvgeniy Ivanov bi_wedge.matchnblks = 1; 40158a2b000SEvgeniy Ivanov 40258a2b000SEvgeniy Ivanov md5(bi_wedge.matchhash, d->buf, d->ll.secsize); 40358a2b000SEvgeniy Ivanov #endif 40458a2b000SEvgeniy Ivanov 40558a2b000SEvgeniy Ivanov return 0; 40658a2b000SEvgeniy Ivanov } 40758a2b000SEvgeniy Ivanov 40858a2b000SEvgeniy Ivanov static int 40958a2b000SEvgeniy Ivanov read_minix_subp(struct biosdisk *d, struct disklabel* dflt_lbl, 41058a2b000SEvgeniy Ivanov int this_ext, daddr_t sector) 41158a2b000SEvgeniy Ivanov { 41258a2b000SEvgeniy Ivanov struct mbr_partition mbr[MBR_PART_COUNT]; 41358a2b000SEvgeniy Ivanov int i; 41458a2b000SEvgeniy Ivanov int typ; 41558a2b000SEvgeniy Ivanov struct partition *p; 41658a2b000SEvgeniy Ivanov 41758a2b000SEvgeniy Ivanov if (readsects(&d->ll, sector, 1, d->buf, 0)) { 41858a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 419*f14fb602SLionel Sambuc printf("Error reading MFS sector %"PRId64"\n", sector); 42058a2b000SEvgeniy Ivanov #endif 42158a2b000SEvgeniy Ivanov return EIO; 42258a2b000SEvgeniy Ivanov } 42358a2b000SEvgeniy Ivanov if ((uint8_t)d->buf[510] != 0x55 || (uint8_t)d->buf[511] != 0xAA) { 42458a2b000SEvgeniy Ivanov return -1; 42558a2b000SEvgeniy Ivanov } 42658a2b000SEvgeniy Ivanov memcpy(&mbr, ((struct mbr_sector *)d->buf)->mbr_parts, sizeof(mbr)); 42758a2b000SEvgeniy Ivanov for (i = 0; i < MBR_PART_COUNT; i++) { 42858a2b000SEvgeniy Ivanov typ = mbr[i].mbrp_type; 42958a2b000SEvgeniy Ivanov if (typ == 0) 43058a2b000SEvgeniy Ivanov continue; 43158a2b000SEvgeniy Ivanov sector = this_ext + mbr[i].mbrp_start; 43258a2b000SEvgeniy Ivanov if (dflt_lbl->d_npartitions >= MAXPARTITIONS) 43358a2b000SEvgeniy Ivanov continue; 43458a2b000SEvgeniy Ivanov p = &dflt_lbl->d_partitions[dflt_lbl->d_npartitions++]; 43558a2b000SEvgeniy Ivanov p->p_offset = sector; 43658a2b000SEvgeniy Ivanov p->p_size = mbr[i].mbrp_size; 43758a2b000SEvgeniy Ivanov p->p_fstype = xlat_mbr_fstype(typ); 43858a2b000SEvgeniy Ivanov } 43958a2b000SEvgeniy Ivanov return 0; 44058a2b000SEvgeniy Ivanov } 44158a2b000SEvgeniy Ivanov 44258a2b000SEvgeniy Ivanov static int 44358a2b000SEvgeniy Ivanov read_label(struct biosdisk *d) 44458a2b000SEvgeniy Ivanov { 44558a2b000SEvgeniy Ivanov struct disklabel dflt_lbl; 44658a2b000SEvgeniy Ivanov struct mbr_partition mbr[MBR_PART_COUNT]; 44758a2b000SEvgeniy Ivanov struct partition *p; 448*f14fb602SLionel Sambuc uint32_t sector; 449*f14fb602SLionel Sambuc int i; 45058a2b000SEvgeniy Ivanov int error; 45158a2b000SEvgeniy Ivanov int typ; 452*f14fb602SLionel Sambuc uint32_t ext_base, this_ext, next_ext; 45358a2b000SEvgeniy Ivanov #ifdef COMPAT_386BSD_MBRPART 45458a2b000SEvgeniy Ivanov int sector_386bsd = -1; 45558a2b000SEvgeniy Ivanov #endif 45658a2b000SEvgeniy Ivanov 45758a2b000SEvgeniy Ivanov memset(&dflt_lbl, 0, sizeof(dflt_lbl)); 45858a2b000SEvgeniy Ivanov dflt_lbl.d_npartitions = 8; 45958a2b000SEvgeniy Ivanov 46058a2b000SEvgeniy Ivanov d->boff = 0; 46158a2b000SEvgeniy Ivanov 46258a2b000SEvgeniy Ivanov if (d->ll.type != BIOSDISK_TYPE_HD) 46358a2b000SEvgeniy Ivanov /* No label on floppy and CD */ 46458a2b000SEvgeniy Ivanov return -1; 46558a2b000SEvgeniy Ivanov 46658a2b000SEvgeniy Ivanov /* 46758a2b000SEvgeniy Ivanov * find NetBSD Partition in DOS partition table 46858a2b000SEvgeniy Ivanov * XXX check magic??? 46958a2b000SEvgeniy Ivanov */ 47058a2b000SEvgeniy Ivanov ext_base = 0; 47158a2b000SEvgeniy Ivanov next_ext = 0; 47258a2b000SEvgeniy Ivanov for (;;) { 47358a2b000SEvgeniy Ivanov this_ext = ext_base + next_ext; 47458a2b000SEvgeniy Ivanov next_ext = 0; 47558a2b000SEvgeniy Ivanov if (readsects(&d->ll, this_ext, 1, d->buf, 0)) { 47658a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 477*f14fb602SLionel Sambuc printf("error reading MBR sector %u\n", this_ext); 47858a2b000SEvgeniy Ivanov #endif 47958a2b000SEvgeniy Ivanov return EIO; 48058a2b000SEvgeniy Ivanov } 48158a2b000SEvgeniy Ivanov memcpy(&mbr, ((struct mbr_sector *)d->buf)->mbr_parts, 48258a2b000SEvgeniy Ivanov sizeof(mbr)); 48358a2b000SEvgeniy Ivanov /* Look for NetBSD partition ID */ 48458a2b000SEvgeniy Ivanov for (i = 0; i < MBR_PART_COUNT; i++) { 48558a2b000SEvgeniy Ivanov typ = mbr[i].mbrp_type; 48658a2b000SEvgeniy Ivanov if (typ == 0) 48758a2b000SEvgeniy Ivanov continue; 48858a2b000SEvgeniy Ivanov sector = this_ext + mbr[i].mbrp_start; 48958a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 490*f14fb602SLionel Sambuc printf("ptn type %d in sector %u\n", typ, sector); 49158a2b000SEvgeniy Ivanov #endif 49258a2b000SEvgeniy Ivanov if (typ == MBR_PTYPE_MINIX_14B) { 49358a2b000SEvgeniy Ivanov if (!read_minix_subp(d, &dflt_lbl, 49458a2b000SEvgeniy Ivanov this_ext, sector)) { 49558a2b000SEvgeniy Ivanov /* Don't add "container" partition */ 49658a2b000SEvgeniy Ivanov continue; 49758a2b000SEvgeniy Ivanov } 49858a2b000SEvgeniy Ivanov } 49958a2b000SEvgeniy Ivanov if (typ == MBR_PTYPE_NETBSD) { 50058a2b000SEvgeniy Ivanov error = check_label(d, sector); 50158a2b000SEvgeniy Ivanov if (error >= 0) 50258a2b000SEvgeniy Ivanov return error; 50358a2b000SEvgeniy Ivanov } 50458a2b000SEvgeniy Ivanov if (MBR_IS_EXTENDED(typ)) { 50558a2b000SEvgeniy Ivanov next_ext = mbr[i].mbrp_start; 50658a2b000SEvgeniy Ivanov continue; 50758a2b000SEvgeniy Ivanov } 50858a2b000SEvgeniy Ivanov #ifdef COMPAT_386BSD_MBRPART 50958a2b000SEvgeniy Ivanov if (this_ext == 0 && typ == MBR_PTYPE_386BSD) 51058a2b000SEvgeniy Ivanov sector_386bsd = sector; 51158a2b000SEvgeniy Ivanov #endif 51258a2b000SEvgeniy Ivanov if (this_ext != 0) { 51358a2b000SEvgeniy Ivanov if (dflt_lbl.d_npartitions >= MAXPARTITIONS) 51458a2b000SEvgeniy Ivanov continue; 51558a2b000SEvgeniy Ivanov p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++]; 51658a2b000SEvgeniy Ivanov } else 51758a2b000SEvgeniy Ivanov p = &dflt_lbl.d_partitions[i]; 51858a2b000SEvgeniy Ivanov p->p_offset = sector; 51958a2b000SEvgeniy Ivanov p->p_size = mbr[i].mbrp_size; 52058a2b000SEvgeniy Ivanov p->p_fstype = xlat_mbr_fstype(typ); 52158a2b000SEvgeniy Ivanov } 52258a2b000SEvgeniy Ivanov if (next_ext == 0) 52358a2b000SEvgeniy Ivanov break; 52458a2b000SEvgeniy Ivanov if (ext_base == 0) { 52558a2b000SEvgeniy Ivanov ext_base = next_ext; 52658a2b000SEvgeniy Ivanov next_ext = 0; 52758a2b000SEvgeniy Ivanov } 52858a2b000SEvgeniy Ivanov } 52958a2b000SEvgeniy Ivanov 53058a2b000SEvgeniy Ivanov sector = 0; 53158a2b000SEvgeniy Ivanov #ifdef COMPAT_386BSD_MBRPART 53258a2b000SEvgeniy Ivanov if (sector_386bsd != -1) { 53358a2b000SEvgeniy Ivanov printf("old BSD partition ID!\n"); 53458a2b000SEvgeniy Ivanov sector = sector_386bsd; 53558a2b000SEvgeniy Ivanov } 53658a2b000SEvgeniy Ivanov #endif 53758a2b000SEvgeniy Ivanov 53858a2b000SEvgeniy Ivanov /* 53958a2b000SEvgeniy Ivanov * One of two things: 54058a2b000SEvgeniy Ivanov * 1. no MBR 54158a2b000SEvgeniy Ivanov * 2. no NetBSD partition in MBR 54258a2b000SEvgeniy Ivanov * 54358a2b000SEvgeniy Ivanov * We simply default to "start of disk" in this case and 54458a2b000SEvgeniy Ivanov * press on. 54558a2b000SEvgeniy Ivanov */ 54658a2b000SEvgeniy Ivanov error = check_label(d, sector); 54758a2b000SEvgeniy Ivanov if (error >= 0) 54858a2b000SEvgeniy Ivanov return error; 54958a2b000SEvgeniy Ivanov 55058a2b000SEvgeniy Ivanov /* 55158a2b000SEvgeniy Ivanov * Nothing at start of disk, return info from mbr partitions. 55258a2b000SEvgeniy Ivanov */ 55358a2b000SEvgeniy Ivanov /* XXX fill it to make checksum match kernel one */ 55458a2b000SEvgeniy Ivanov dflt_lbl.d_checksum = dkcksum(&dflt_lbl); 55558a2b000SEvgeniy Ivanov ingest_label(d, &dflt_lbl); 55658a2b000SEvgeniy Ivanov return 0; 55758a2b000SEvgeniy Ivanov } 55858a2b000SEvgeniy Ivanov #endif /* NO_DISKLABEL */ 55958a2b000SEvgeniy Ivanov 56058a2b000SEvgeniy Ivanov #if !defined(NO_DISKLABEL) || !defined(NO_GPT) 56158a2b000SEvgeniy Ivanov static int 56258a2b000SEvgeniy Ivanov read_partitions(struct biosdisk *d) 56358a2b000SEvgeniy Ivanov { 56458a2b000SEvgeniy Ivanov int error; 56558a2b000SEvgeniy Ivanov 56658a2b000SEvgeniy Ivanov error = -1; 56758a2b000SEvgeniy Ivanov 56858a2b000SEvgeniy Ivanov #ifndef NO_GPT 56958a2b000SEvgeniy Ivanov error = read_gpt(d); 57058a2b000SEvgeniy Ivanov if (error == 0) 57158a2b000SEvgeniy Ivanov return 0; 57258a2b000SEvgeniy Ivanov 57358a2b000SEvgeniy Ivanov #endif 57458a2b000SEvgeniy Ivanov #ifndef NO_DISKLABEL 57558a2b000SEvgeniy Ivanov error = read_label(d); 57658a2b000SEvgeniy Ivanov 57758a2b000SEvgeniy Ivanov #endif 57858a2b000SEvgeniy Ivanov return error; 57958a2b000SEvgeniy Ivanov } 58058a2b000SEvgeniy Ivanov #endif 58158a2b000SEvgeniy Ivanov 58258a2b000SEvgeniy Ivanov void 58358a2b000SEvgeniy Ivanov biosdisk_probe(void) 58458a2b000SEvgeniy Ivanov { 58558a2b000SEvgeniy Ivanov struct biosdisk d; 58658a2b000SEvgeniy Ivanov struct biosdisk_extinfo ed; 58758a2b000SEvgeniy Ivanov uint64_t size; 58858a2b000SEvgeniy Ivanov int first; 58958a2b000SEvgeniy Ivanov int i; 59058a2b000SEvgeniy Ivanov #if !defined(NO_DISKLABEL) || !defined(NO_GPT) 59158a2b000SEvgeniy Ivanov int part; 59258a2b000SEvgeniy Ivanov #endif 59358a2b000SEvgeniy Ivanov 59458a2b000SEvgeniy Ivanov for (i = 0; i < MAX_BIOSDISKS + 2; i++) { 59558a2b000SEvgeniy Ivanov first = 1; 59658a2b000SEvgeniy Ivanov memset(&d, 0, sizeof(d)); 59758a2b000SEvgeniy Ivanov memset(&ed, 0, sizeof(ed)); 59858a2b000SEvgeniy Ivanov if (i >= MAX_BIOSDISKS) 59958a2b000SEvgeniy Ivanov d.ll.dev = 0x00 + i - MAX_BIOSDISKS; /* fd */ 60058a2b000SEvgeniy Ivanov else 60158a2b000SEvgeniy Ivanov d.ll.dev = 0x80 + i; /* hd/cd */ 60258a2b000SEvgeniy Ivanov if (set_geometry(&d.ll, &ed)) 60358a2b000SEvgeniy Ivanov continue; 60458a2b000SEvgeniy Ivanov printf("disk "); 60558a2b000SEvgeniy Ivanov switch (d.ll.type) { 60658a2b000SEvgeniy Ivanov case BIOSDISK_TYPE_CD: 60758a2b000SEvgeniy Ivanov printf("cd0\n cd0a\n"); 60858a2b000SEvgeniy Ivanov break; 60958a2b000SEvgeniy Ivanov case BIOSDISK_TYPE_FD: 61058a2b000SEvgeniy Ivanov printf("fd%d\n", d.ll.dev & 0x7f); 61158a2b000SEvgeniy Ivanov printf(" fd%da\n", d.ll.dev & 0x7f); 61258a2b000SEvgeniy Ivanov break; 61358a2b000SEvgeniy Ivanov case BIOSDISK_TYPE_HD: 61458a2b000SEvgeniy Ivanov printf("hd%d", d.ll.dev & 0x7f); 61558a2b000SEvgeniy Ivanov if (d.ll.flags & BIOSDISK_INT13EXT) { 61658a2b000SEvgeniy Ivanov printf(" size "); 61758a2b000SEvgeniy Ivanov size = ed.totsec * ed.sbytes; 61858a2b000SEvgeniy Ivanov if (size >= (10ULL * 1024 * 1024 * 1024)) 61958a2b000SEvgeniy Ivanov printf("%"PRIu64" GB", 62058a2b000SEvgeniy Ivanov size / (1024 * 1024 * 1024)); 62158a2b000SEvgeniy Ivanov else 62258a2b000SEvgeniy Ivanov printf("%"PRIu64" MB", 62358a2b000SEvgeniy Ivanov size / (1024 * 1024)); 62458a2b000SEvgeniy Ivanov } 62558a2b000SEvgeniy Ivanov printf("\n"); 62658a2b000SEvgeniy Ivanov break; 62758a2b000SEvgeniy Ivanov } 62858a2b000SEvgeniy Ivanov #if !defined(NO_DISKLABEL) || !defined(NO_GPT) 62958a2b000SEvgeniy Ivanov if (d.ll.type != BIOSDISK_TYPE_HD) 63058a2b000SEvgeniy Ivanov continue; 63158a2b000SEvgeniy Ivanov 63258a2b000SEvgeniy Ivanov if (read_partitions(&d) != 0) 63358a2b000SEvgeniy Ivanov continue; 63458a2b000SEvgeniy Ivanov 63558a2b000SEvgeniy Ivanov for (part = 0; part < BIOSDISKNPART; part++) { 63658a2b000SEvgeniy Ivanov if (d.part[part].size == 0) 63758a2b000SEvgeniy Ivanov continue; 63858a2b000SEvgeniy Ivanov if (d.part[part].fstype == FS_UNUSED) 63958a2b000SEvgeniy Ivanov continue; 64058a2b000SEvgeniy Ivanov if (first) { 64158a2b000SEvgeniy Ivanov printf(" "); 64258a2b000SEvgeniy Ivanov first = 0; 64358a2b000SEvgeniy Ivanov } 64458a2b000SEvgeniy Ivanov printf(" hd%d%c(", d.ll.dev & 0x7f, part + 'a'); 64558a2b000SEvgeniy Ivanov if (d.part[part].fstype < FSMAXTYPES) 64658a2b000SEvgeniy Ivanov printf("%s", 64758a2b000SEvgeniy Ivanov fstypenames[d.part[part].fstype]); 64858a2b000SEvgeniy Ivanov else 64958a2b000SEvgeniy Ivanov printf("%d", d.part[part].fstype); 65058a2b000SEvgeniy Ivanov printf(")"); 65158a2b000SEvgeniy Ivanov } 65258a2b000SEvgeniy Ivanov #endif 65358a2b000SEvgeniy Ivanov if (first == 0) 65458a2b000SEvgeniy Ivanov printf("\n"); 65558a2b000SEvgeniy Ivanov } 65658a2b000SEvgeniy Ivanov } 65758a2b000SEvgeniy Ivanov 65858a2b000SEvgeniy Ivanov /* Determine likely partition for possible sector number of dos 65958a2b000SEvgeniy Ivanov * partition. 66058a2b000SEvgeniy Ivanov */ 66158a2b000SEvgeniy Ivanov 66258a2b000SEvgeniy Ivanov int 66358a2b000SEvgeniy Ivanov biosdisk_findpartition(int biosdev, daddr_t sector) 66458a2b000SEvgeniy Ivanov { 66558a2b000SEvgeniy Ivanov #if defined(NO_DISKLABEL) && defined(NO_GPT) 66658a2b000SEvgeniy Ivanov return 0; 66758a2b000SEvgeniy Ivanov #else 66858a2b000SEvgeniy Ivanov struct biosdisk *d; 66958a2b000SEvgeniy Ivanov int partition = 0; 67058a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 67158a2b000SEvgeniy Ivanov printf("looking for partition device %x, sector %"PRId64"\n", biosdev, sector); 67258a2b000SEvgeniy Ivanov #endif 67358a2b000SEvgeniy Ivanov 67458a2b000SEvgeniy Ivanov /* Look for netbsd partition that is the dos boot one */ 67558a2b000SEvgeniy Ivanov d = alloc_biosdisk(biosdev); 67658a2b000SEvgeniy Ivanov if (d == NULL) 67758a2b000SEvgeniy Ivanov return 0; 67858a2b000SEvgeniy Ivanov 67958a2b000SEvgeniy Ivanov if (read_partitions(d) == 0) { 68058a2b000SEvgeniy Ivanov for (partition = (BIOSDISKNPART-1); --partition;) { 68158a2b000SEvgeniy Ivanov if (d->part[partition].fstype == FS_UNUSED) 68258a2b000SEvgeniy Ivanov continue; 68358a2b000SEvgeniy Ivanov if (d->part[partition].offset == sector) 68458a2b000SEvgeniy Ivanov break; 68558a2b000SEvgeniy Ivanov } 68658a2b000SEvgeniy Ivanov } 68758a2b000SEvgeniy Ivanov 68858a2b000SEvgeniy Ivanov dealloc(d, sizeof(*d)); 68958a2b000SEvgeniy Ivanov return partition; 69058a2b000SEvgeniy Ivanov #endif /* NO_DISKLABEL && NO_GPT */ 69158a2b000SEvgeniy Ivanov } 69258a2b000SEvgeniy Ivanov 69358a2b000SEvgeniy Ivanov #ifdef _STANDALONE 69458a2b000SEvgeniy Ivanov static void 69558a2b000SEvgeniy Ivanov add_biosdisk_bootinfo(void) 69658a2b000SEvgeniy Ivanov { 69758a2b000SEvgeniy Ivanov static bool done; 69858a2b000SEvgeniy Ivanov 69958a2b000SEvgeniy Ivanov if (bootinfo == NULL) { 70058a2b000SEvgeniy Ivanov done = false; 70158a2b000SEvgeniy Ivanov return; 70258a2b000SEvgeniy Ivanov } 70358a2b000SEvgeniy Ivanov 70458a2b000SEvgeniy Ivanov if (done) 70558a2b000SEvgeniy Ivanov return; 70658a2b000SEvgeniy Ivanov 70758a2b000SEvgeniy Ivanov BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk)); 70858a2b000SEvgeniy Ivanov BI_ADD(&bi_wedge, BTINFO_BOOTWEDGE, sizeof(bi_wedge)); 70958a2b000SEvgeniy Ivanov 71058a2b000SEvgeniy Ivanov done = true; 71158a2b000SEvgeniy Ivanov 71258a2b000SEvgeniy Ivanov return; 71358a2b000SEvgeniy Ivanov } 71458a2b000SEvgeniy Ivanov 71558a2b000SEvgeniy Ivanov #endif 71658a2b000SEvgeniy Ivanov 71758a2b000SEvgeniy Ivanov int 71858a2b000SEvgeniy Ivanov biosdisk_open(struct open_file *f, ...) 71958a2b000SEvgeniy Ivanov /* struct open_file *f, int biosdev, int partition */ 72058a2b000SEvgeniy Ivanov { 72158a2b000SEvgeniy Ivanov va_list ap; 72258a2b000SEvgeniy Ivanov struct biosdisk *d; 72358a2b000SEvgeniy Ivanov int biosdev; 72458a2b000SEvgeniy Ivanov int partition; 72558a2b000SEvgeniy Ivanov int error = 0; 72658a2b000SEvgeniy Ivanov 72758a2b000SEvgeniy Ivanov va_start(ap, f); 72858a2b000SEvgeniy Ivanov biosdev = va_arg(ap, int); 72958a2b000SEvgeniy Ivanov d = alloc_biosdisk(biosdev); 73058a2b000SEvgeniy Ivanov if (d == NULL) { 73158a2b000SEvgeniy Ivanov error = ENXIO; 73258a2b000SEvgeniy Ivanov goto out; 73358a2b000SEvgeniy Ivanov } 73458a2b000SEvgeniy Ivanov 73558a2b000SEvgeniy Ivanov partition = va_arg(ap, int); 73658a2b000SEvgeniy Ivanov #ifdef _STANDALONE 73758a2b000SEvgeniy Ivanov bi_disk.biosdev = d->ll.dev; 73858a2b000SEvgeniy Ivanov bi_disk.partition = partition; 73958a2b000SEvgeniy Ivanov bi_disk.labelsector = -1; 74058a2b000SEvgeniy Ivanov 74158a2b000SEvgeniy Ivanov bi_wedge.biosdev = d->ll.dev; 74258a2b000SEvgeniy Ivanov bi_wedge.matchblk = -1; 74358a2b000SEvgeniy Ivanov #endif 74458a2b000SEvgeniy Ivanov 74558a2b000SEvgeniy Ivanov #if !defined(NO_DISKLABEL) || !defined(NO_GPT) 74658a2b000SEvgeniy Ivanov error = read_partitions(d); 74758a2b000SEvgeniy Ivanov if (error == -1) { 74858a2b000SEvgeniy Ivanov error = 0; 74958a2b000SEvgeniy Ivanov goto nolabel; 75058a2b000SEvgeniy Ivanov } 75158a2b000SEvgeniy Ivanov if (error) 75258a2b000SEvgeniy Ivanov goto out; 75358a2b000SEvgeniy Ivanov 75458a2b000SEvgeniy Ivanov if (partition >= BIOSDISKNPART || 75558a2b000SEvgeniy Ivanov d->part[partition].fstype == FS_UNUSED) { 75658a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 75758a2b000SEvgeniy Ivanov printf("illegal partition\n"); 75858a2b000SEvgeniy Ivanov #endif 75958a2b000SEvgeniy Ivanov error = EPART; 76058a2b000SEvgeniy Ivanov goto out; 76158a2b000SEvgeniy Ivanov } 76258a2b000SEvgeniy Ivanov 76358a2b000SEvgeniy Ivanov d->boff = d->part[partition].offset; 76458a2b000SEvgeniy Ivanov 76558a2b000SEvgeniy Ivanov if (d->part[partition].fstype == FS_RAID) 76658a2b000SEvgeniy Ivanov d->boff += RF_PROTECTED_SECTORS; 76758a2b000SEvgeniy Ivanov 76858a2b000SEvgeniy Ivanov #ifdef _STANDALONE 76958a2b000SEvgeniy Ivanov bi_wedge.startblk = d->part[partition].offset; 77058a2b000SEvgeniy Ivanov bi_wedge.nblks = d->part[partition].size; 77158a2b000SEvgeniy Ivanov #endif 77258a2b000SEvgeniy Ivanov 77358a2b000SEvgeniy Ivanov nolabel: 77458a2b000SEvgeniy Ivanov #endif 77558a2b000SEvgeniy Ivanov #ifdef DISK_DEBUG 77658a2b000SEvgeniy Ivanov printf("partition @%"PRId64"\n", d->boff); 77758a2b000SEvgeniy Ivanov #endif 77858a2b000SEvgeniy Ivanov 77958a2b000SEvgeniy Ivanov #ifdef _STANDALONE 78058a2b000SEvgeniy Ivanov add_biosdisk_bootinfo(); 78158a2b000SEvgeniy Ivanov #endif 78258a2b000SEvgeniy Ivanov 78358a2b000SEvgeniy Ivanov f->f_devdata = d; 78458a2b000SEvgeniy Ivanov out: 78558a2b000SEvgeniy Ivanov va_end(ap); 78658a2b000SEvgeniy Ivanov if (error) 78758a2b000SEvgeniy Ivanov dealloc(d, sizeof(*d)); 78858a2b000SEvgeniy Ivanov return error; 78958a2b000SEvgeniy Ivanov } 79058a2b000SEvgeniy Ivanov 79158a2b000SEvgeniy Ivanov #ifndef LIBSA_NO_FS_CLOSE 79258a2b000SEvgeniy Ivanov int 79358a2b000SEvgeniy Ivanov biosdisk_close(struct open_file *f) 79458a2b000SEvgeniy Ivanov { 79558a2b000SEvgeniy Ivanov struct biosdisk *d = f->f_devdata; 79658a2b000SEvgeniy Ivanov 79758a2b000SEvgeniy Ivanov /* let the floppy drive go off */ 79858a2b000SEvgeniy Ivanov if (d->ll.type == BIOSDISK_TYPE_FD) 79958a2b000SEvgeniy Ivanov wait_sec(3); /* 2s is enough on all PCs I found */ 80058a2b000SEvgeniy Ivanov 80158a2b000SEvgeniy Ivanov dealloc(d, sizeof(*d)); 80258a2b000SEvgeniy Ivanov f->f_devdata = NULL; 80358a2b000SEvgeniy Ivanov return 0; 80458a2b000SEvgeniy Ivanov } 80558a2b000SEvgeniy Ivanov #endif 80658a2b000SEvgeniy Ivanov 80758a2b000SEvgeniy Ivanov int 80858a2b000SEvgeniy Ivanov biosdisk_ioctl(struct open_file *f, u_long cmd, void *arg) 80958a2b000SEvgeniy Ivanov { 81058a2b000SEvgeniy Ivanov return EIO; 81158a2b000SEvgeniy Ivanov } 812