[BACK]Return to mbr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / distrib / utils / sysinst

Annotation of src/distrib/utils/sysinst/mbr.c, Revision 1.14

1.14    ! bouyer      1: /*     $NetBSD: mbr.c,v 1.13 1999/04/11 22:40:20 bouyer Exp $ */
1.1       phil        2:
                      3: /*
                      4:  * Copyright 1997 Piermont Information Systems Inc.
                      5:  * All rights reserved.
1.6       jonathan    6:  * * Copyright 1997 Piermont Information Systems Inc.
                      7:  * All rights reserved.
1.1       phil        8:  *
                      9:  * Written by Philip A. Nelson for Piermont Information Systems Inc.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *      This product includes software develooped for the NetBSD Project by
                     22:  *      Piermont Information Systems Inc.
                     23:  * 4. The name of Piermont Information Systems Inc. may not be used to endorse
                     24:  *    or promote products derived from this software without specific prior
                     25:  *    written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
                     28:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     29:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     30:  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
                     31:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     37:  * THE POSSIBILITY OF SUCH DAMAGE.
                     38:  *
                     39:  */
                     40:
1.10      fvdl       41: /*
                     42:  * Following applies to the geometry guessing code
                     43:  */
                     44:
                     45: /*
                     46:  * Mach Operating System
                     47:  * Copyright (c) 1992 Carnegie Mellon University
                     48:  * All Rights Reserved.
                     49:  *
                     50:  * Permission to use, copy, modify and distribute this software and its
                     51:  * documentation is hereby granted, provided that both the copyright
                     52:  * notice and this permission notice appear in all copies of the
                     53:  * software, derivative works or modified versions, and any portions
                     54:  * thereof, and that both notices appear in supporting documentation.
                     55:  *
                     56:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     57:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     58:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     59:  *
                     60:  * Carnegie Mellon requests users of this software to return to
                     61:  *
                     62:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     63:  *  School of Computer Science
                     64:  *  Carnegie Mellon University
                     65:  *  Pittsburgh PA 15213-3890
                     66:  *
                     67:  * any improvements or extensions that they make and grant Carnegie Mellon
                     68:  * the rights to redistribute these changes.
                     69:  */
                     70:
1.6       jonathan   71: /* mbr.c -- DOS Master Boot Record editing code */
1.1       phil       72:
1.10      fvdl       73: #include <sys/param.h>
                     74: #include <sys/types.h>
1.1       phil       75: #include <stdio.h>
1.10      fvdl       76: #include <unistd.h>
                     77: #include <fcntl.h>
1.6       jonathan   78: #include <util.h>
1.1       phil       79: #include "defs.h"
1.10      fvdl       80: #include "mbr.h"
1.1       phil       81: #include "md.h"
                     82: #include "msg_defs.h"
                     83: #include "menu_defs.h"
1.10      fvdl       84: #include "endian.h"
1.1       phil       85:
                     86: struct part_id {
                     87:        int id;
                     88:        char *name;
                     89: } part_ids[] = {
                     90:        {0, "unused"},
1.10      fvdl       91:        {MBR_PTYPE_FAT12, "Primary DOS, 12 bit FAT"},
                     92:        {MBR_PTYPE_FAT16S, "Primary DOS, 16 bit FAT <32M"},
                     93:        {MBR_PTYPE_EXT, "Extended DOS"},
                     94:        {MBR_PTYPE_FAT16B, "Primary DOS, 16-bit FAT >32MB"},
                     95:        {MBR_PTYPE_NTFS, "NTFS"},
                     96:        {MBR_PTYPE_LNXSWAP, "Linux swap"},
                     97:        {MBR_PTYPE_LNXEXT2, "Linux native"},
                     98:        {MBR_PTYPE_386BSD, "old NetBSD/FreeBSD/386BSD"},
                     99:        {MBR_PTYPE_NETBSD, "NetBSD"},
1.1       phil      100:        {-1, "Unknown"},
                    101: };
                    102:
1.10      fvdl      103: int dosptyp_nbsd = MBR_PTYPE_NETBSD;
                    104:
                    105: static int get_mapping __P((struct mbr_partition *, int, int *, int *, int *,
                    106:                            long *absolute));
                    107: static void convert_mbr_chs __P((int, int, int, u_int8_t *, u_int8_t *,
                    108:                                 u_int8_t *, u_int32_t));
1.6       jonathan  109:
                    110:
                    111: /*
                    112:  * First, geometry  stuff...
                    113:  */
1.7       mrg       114: int
                    115: check_geom()
1.6       jonathan  116: {
1.7       mrg       117:
1.6       jonathan  118:        return bcyl <= 1024 && bsec < 64 && bcyl > 0 && bhead > 0 && bsec > 0;
                    119: }
                    120:
                    121: /*
                    122:  * get C/H/S geometry from user via menu interface and
                    123:  * store in globals.
                    124:  */
1.7       mrg       125: void
1.10      fvdl      126: set_bios_geom(cyl, head, sec)
                    127:        int cyl, head, sec;
1.6       jonathan  128: {
                    129:        char res[80];
1.7       mrg       130:
1.6       jonathan  131:        msg_display_add(MSG_setbiosgeom);
1.10      fvdl      132:        snprintf(res, 80, "%d", cyl);
1.8       rvb       133:        msg_prompt_add(MSG_cylinders, res, res, 80);
1.6       jonathan  134:        bcyl = atoi(res);
1.8       rvb       135:
1.10      fvdl      136:        snprintf(res, 80, "%d", head);
1.8       rvb       137:        msg_prompt_add(MSG_heads, res, res, 80);
1.6       jonathan  138:        bhead = atoi(res);
1.8       rvb       139:
1.10      fvdl      140:        snprintf(res, 80, "%d", sec);
1.8       rvb       141:        msg_prompt_add(MSG_sectors, res, res, 80);
1.6       jonathan  142:        bsec = atoi(res);
                    143: }
                    144:
1.7       mrg       145: void
                    146: disp_cur_geom()
                    147: {
1.6       jonathan  148:
                    149:        msg_display_add(MSG_realgeom, dlcyl, dlhead, dlsec);
                    150:        msg_display_add(MSG_biosgeom, bcyl, bhead, bsec);
                    151: }
                    152:
                    153:
                    154: /*
                    155:  * Then,  the partition stuff...
                    156:  */
                    157: int
1.7       mrg       158: otherpart(id)
                    159:        int id;
1.6       jonathan  160: {
1.7       mrg       161:
1.10      fvdl      162:        return (id != 0 && id != MBR_PTYPE_386BSD && id != MBR_PTYPE_NETBSD);
1.6       jonathan  163: }
                    164:
                    165: int
1.7       mrg       166: ourpart(id)
                    167:        int id;
1.6       jonathan  168: {
1.7       mrg       169:
1.10      fvdl      170:        return (id == MBR_PTYPE_386BSD || id == MBR_PTYPE_NETBSD);
1.6       jonathan  171: }
                    172:
                    173: /*
                    174:  * Let user change incore Master Boot Record partitions via menu.
                    175:  */
1.7       mrg       176: int
1.10      fvdl      177: edit_mbr(partition)
                    178:        struct mbr_partition *partition;
1.6       jonathan  179: {
                    180:        int i, j;
                    181:
                    182:        /* Ask full/part */
1.10      fvdl      183:
                    184:        /* XXX this sucks ("part" is used in menus, no param passing there) */
                    185:        part = partition;
1.7       mrg       186:        msg_display(MSG_fullpart, diskdev);
                    187:        process_menu(MENU_fullpart);
1.6       jonathan  188:
                    189:        /* DOS fdisk label checking and value setting. */
                    190:        if (usefull) {
                    191:                int otherparts = 0;
                    192:                int ourparts = 0;
                    193:
                    194:                int i;
                    195:                /* Count nonempty, non-BSD partitions. */
1.10      fvdl      196:                for (i = 0; i < NMBRPART; i++) {
1.14    ! bouyer    197:                        otherparts += otherpart(part[i].mbrp_typ);
1.6       jonathan  198:                        /* check for dualboot *bsd too */
1.14    ! bouyer    199:                        ourparts += ourpart(part[i].mbrp_typ);
1.6       jonathan  200:                }
                    201:
                    202:                /* Ask if we really want to blow away non-NetBSD stuff */
                    203:                if (otherparts != 0 || ourparts > 1) {
1.7       mrg       204:                        msg_display(MSG_ovrwrite);
                    205:                        process_menu(MENU_noyes);
1.6       jonathan  206:                        if (!yesno) {
1.9       garbled   207:                                if (logging)
                    208:                                        (void)fprintf(log, "User answered no to destroy other data, aborting.\n");
1.6       jonathan  209:                                return 0;
                    210:                        }
                    211:                }
                    212:
                    213:                /* Set the partition information for full disk usage. */
1.14    ! bouyer    214:                part[0].mbrp_typ = part[0].mbrp_flag = 0;
        !           215:                part[0].mbrp_start = part[0].mbrp_size = 0;
        !           216:                part[1].mbrp_typ = part[0].mbrp_flag = 0;
        !           217:                part[1].mbrp_start = part[0].mbrp_size = 0;
        !           218:                part[2].mbrp_typ = part[0].mbrp_flag = 0;
        !           219:                part[2].mbrp_start = part[0].mbrp_size = 0;
1.10      fvdl      220:                part[3].mbrp_typ = dosptyp_nbsd;
                    221:                part[3].mbrp_size = bsize - bsec;
                    222:                part[3].mbrp_start = bsec;
                    223:                part[3].mbrp_flag = 0x80;
1.6       jonathan  224:
                    225:                ptstart = bsec;
                    226:                ptsize = bsize - bsec;
                    227:                fsdsize = dlsize;
                    228:                fsptsize = dlsize - bsec;
                    229:                fsdmb = fsdsize / MEG;
                    230:                activepart = 3;
                    231:        } else {
                    232:                int numbsd, overlap;
                    233:                int numfreebsd, freebsdpart;    /* dual-boot */
                    234:
                    235:                /* Ask for sizes, which partitions, ... */
                    236:                ask_sizemult();
                    237:                bsdpart = freebsdpart = -1;
                    238:                activepart = -1;
1.7       mrg       239:                for (i = 0; i<4; i++)
1.13      bouyer    240:                        if (part[i].mbrp_flag != 0) {
1.6       jonathan  241:                                activepart = i;
1.13      bouyer    242:                                part[i].mbrp_flag = 0;
                    243:                        }
1.6       jonathan  244:                do {
                    245:                        process_menu (MENU_editparttable);
                    246:                        numbsd = 0;
                    247:                        bsdpart = -1;
                    248:                        freebsdpart = -1;
                    249:                        numfreebsd = 0;
                    250:                        overlap = 0;
                    251:                        yesno = 0;
                    252:                        for (i=0; i<4; i++) {
1.7       mrg       253:                                /* Count 386bsd/FreeBSD/NetBSD(old) partitions */
1.10      fvdl      254:                                if (part[i].mbrp_typ == MBR_PTYPE_386BSD) {
1.6       jonathan  255:                                        freebsdpart = i;
                    256:                                        numfreebsd++;
                    257:                                }
                    258:                                /* Count NetBSD-only partitions */
1.10      fvdl      259:                                if (part[i].mbrp_typ == MBR_PTYPE_NETBSD) {
1.6       jonathan  260:                                        bsdpart = i;
                    261:                                        numbsd++;
                    262:                                }
                    263:                                for (j = i+1; j<4; j++)
1.10      fvdl      264:                                       if (partsoverlap(part, i,j))
1.6       jonathan  265:                                               overlap = 1;
                    266:                        }
                    267:
                    268:                        /* If no new-NetBSD partition, use 386bsd instead */
                    269:                        if (numbsd == 0 && numfreebsd > 0) {
                    270:                                numbsd = numfreebsd;
                    271:                                bsdpart = freebsdpart;
                    272:                                /* XXX check partition type? */
                    273:                        }
                    274:
                    275:                        /* Check for overlap or multiple native partitions */
                    276:                        if (overlap || numbsd != 1) {
1.7       mrg       277:                                msg_display(MSG_reeditpart);
                    278:                                process_menu(MENU_yesno);
1.6       jonathan  279:                        }
                    280:                } while (yesno && (numbsd != 1 || overlap));
1.11      fvdl      281:
                    282:                if (activepart != -1)
                    283:                        part[activepart].mbrp_flag = 0x80;
1.6       jonathan  284:
                    285:                if (numbsd == 0) {
1.7       mrg       286:                        msg_display(MSG_nobsdpart);
                    287:                        process_menu(MENU_ok);
1.6       jonathan  288:                        return 0;
                    289:                }
                    290:
                    291:                if (numbsd > 1) {
1.7       mrg       292:                        msg_display(MSG_multbsdpart, bsdpart);
                    293:                        process_menu(MENU_ok);
1.6       jonathan  294:                }
                    295:
1.10      fvdl      296:                ptstart = part[bsdpart].mbrp_start;
                    297:                ptsize = part[bsdpart].mbrp_size;
1.6       jonathan  298:                fsdsize = dlsize;
                    299:                if (ptstart + ptsize < bsize)
                    300:                        fsptsize = ptsize;
                    301:                else
                    302:                        fsptsize = dlsize - ptstart;
                    303:                fsdmb = fsdsize / MEG;
                    304:
                    305:                /* Ask if a boot selector is wanted. XXXX */
                    306:        }
                    307:
                    308:        /* Compute minimum NetBSD partition sizes (in sectors). */
                    309:        minfsdmb = (80 + 4*rammb) * (MEG / sectorsize);
                    310:
                    311:        return 1;
                    312: }
                    313:
1.7       mrg       314: int
1.10      fvdl      315: partsoverlap(part, i, j)
                    316:        struct mbr_partition *part;
1.7       mrg       317:        int i;
                    318:        int j;
1.1       phil      319: {
1.7       mrg       320:
1.10      fvdl      321:        if (part[i].mbrp_size == 0 || part[j].mbrp_size == 0)
1.1       phil      322:                return 0;
                    323:
1.2       phil      324:        return
1.10      fvdl      325:                (part[i].mbrp_start < part[j].mbrp_start &&
                    326:                 part[i].mbrp_start + part[i].mbrp_size > part[j].mbrp_start)
1.1       phil      327:                ||
1.10      fvdl      328:                (part[i].mbrp_start > part[j].mbrp_start &&
                    329:                 part[i].mbrp_start < part[j].mbrp_start + part[j].mbrp_size)
1.1       phil      330:                ||
1.10      fvdl      331:                (part[i].mbrp_start == part[j].mbrp_start);
1.1       phil      332: }
                    333:
1.7       mrg       334: void
1.10      fvdl      335: disp_cur_part(part, sel, disp)
                    336:        struct mbr_partition *part;
1.7       mrg       337:        int sel;
                    338:        int disp;
1.1       phil      339: {
1.4       fvdl      340:        int i, j, start, stop, rsize, rend;
1.1       phil      341:
                    342:        if (disp < 0)
                    343:                start = 0, stop = 4;
                    344:        else
                    345:                start = disp, stop = disp+1;
1.7       mrg       346:        msg_display_add(MSG_part_head, multname, multname, multname);
                    347:        for (i = start; i < stop; i++) {
                    348:                if (sel == i)
                    349:                        msg_standout();
1.10      fvdl      350:                if (part[i].mbrp_size == 0 && part[i].mbrp_start == 0)
1.7       mrg       351:                        msg_printf_add("%d %36s  ", i, "");
1.4       fvdl      352:                else {
1.10      fvdl      353:                        rsize = part[i].mbrp_size / sizemult;
                    354:                        if (part[i].mbrp_size % sizemult)
1.4       fvdl      355:                                rsize++;
1.10      fvdl      356:                        rend = (part[i].mbrp_start + part[i].mbrp_size) / sizemult;
                    357:                        if ((part[i].mbrp_size + part[i].mbrp_size) % sizemult)
1.4       fvdl      358:                                rend++;
                    359:                        msg_printf_add("%d %12d%12d%12d  ", i,
1.10      fvdl      360:                            part[i].mbrp_start / sizemult, rsize, rend);
1.4       fvdl      361:                }
1.1       phil      362:                for (j = 0; part_ids[j].id != -1 &&
1.10      fvdl      363:                            part_ids[j].id != part[i].mbrp_typ; j++);
                    364:                msg_printf_add("%s\n", part_ids[j].name);
                    365:                if (sel == i)
                    366:                        msg_standend();
                    367:        }
                    368: }
                    369:
                    370: int
                    371: read_mbr(disk, buf, len)
                    372:        char *disk, *buf;
                    373:        int len;
                    374: {
                    375:        char diskpath[MAXPATHLEN];
                    376:        int fd, i;
                    377:        struct mbr_partition *mbrp;
                    378:
                    379:        /* Open the disk. */
                    380:        fd = opendisk(disk, O_RDONLY, diskpath, sizeof(diskpath), 0);
                    381:        if (fd < 0)
                    382:                return -1;
                    383:
                    384:        if (lseek(fd, MBR_BBSECTOR * MBR_SECSIZE, SEEK_SET) < 0) {
                    385:                close(fd);
                    386:                return -1;
                    387:        }
                    388:        if (read(fd, buf, len) < len) {
                    389:                close(fd);
                    390:                return -1;
                    391:        }
                    392:
                    393:        if (valid_mbr(buf)) {
                    394:                mbrp = (struct mbr_partition *)&buf[MBR_PARTOFF];
                    395:                for (i = 0; i < NMBRPART; i++) {
                    396:                        if (mbrp[i].mbrp_typ != 0) {
                    397:                                mbrp[i].mbrp_start =
                    398:                                    le_to_native32(mbrp[i].mbrp_start);
                    399:                                mbrp[i].mbrp_size =
                    400:                                    le_to_native32(mbrp[i].mbrp_size);
                    401:                        }
                    402:                }
                    403:        }
                    404:
                    405:        (void)close(fd);
                    406:        return 0;
                    407: }
                    408:
                    409: int
                    410: write_mbr(disk, buf, len)
                    411:        char *disk, *buf;
                    412:        int len;
                    413: {
                    414:        char diskpath[MAXPATHLEN];
                    415:        int fd, i, ret = 0;
                    416:        struct mbr_partition *mbrp;
                    417:        u_int32_t pstart, psize;
                    418:
                    419:        /* Open the disk. */
                    420:        fd = opendisk(disk, O_WRONLY, diskpath, sizeof(diskpath), 0);
                    421:        if (fd < 0)
                    422:                return -1;
                    423:
                    424:        if (lseek(fd, MBR_BBSECTOR * MBR_SECSIZE, SEEK_SET) < 0) {
                    425:                close(fd);
                    426:                return -1;
                    427:        }
                    428:
                    429:        mbrp = (struct mbr_partition *)&buf[MBR_PARTOFF];
                    430:        for (i = 0; i < NMBRPART; i++) {
1.14    ! bouyer    431:                if (mbrp[i].mbrp_start == 0 &&
        !           432:                    mbrp[i].mbrp_size == 0) {
        !           433:                        mbrp[i].mbrp_scyl = 0;
        !           434:                        mbrp[i].mbrp_shd = 0;
        !           435:                        mbrp[i].mbrp_ssect = 0;
        !           436:                        mbrp[i].mbrp_ecyl = 0;
        !           437:                        mbrp[i].mbrp_ehd = 0;
        !           438:                        mbrp[i].mbrp_esect = 0;
        !           439:                } else {
1.10      fvdl      440:                        pstart = mbrp[i].mbrp_start;
                    441:                        psize = mbrp[i].mbrp_size;
                    442:                        mbrp[i].mbrp_start = native_to_le32(pstart);
                    443:                        mbrp[i].mbrp_size = native_to_le32(psize);
                    444:                        convert_mbr_chs(bcyl, bhead, bsec,
                    445:                            &mbrp[i].mbrp_scyl, &mbrp[i].mbrp_shd,
                    446:                            &mbrp[i].mbrp_ssect, pstart);
                    447:                        convert_mbr_chs(bcyl, bhead, bsec,
                    448:                            &mbrp[i].mbrp_ecyl, &mbrp[i].mbrp_ehd,
                    449:                            &mbrp[i].mbrp_esect, pstart + psize);
                    450:                }
                    451:        }
                    452:
                    453:        if (write(fd, buf, len) < 0)
                    454:                ret = -1;
                    455:
                    456:        (void)close(fd);
                    457:        return ret;
                    458: }
                    459:
                    460: int
                    461: valid_mbr(buf)
                    462:        char *buf;
                    463: {
1.12      fvdl      464:        u_int16_t magic;
1.10      fvdl      465:
1.12      fvdl      466:        magic = *((u_int16_t *)&buf[MBR_MAGICOFF]);
1.10      fvdl      467:
                    468:        return (le_to_native16(magic) == MBR_MAGIC);
                    469: }
                    470:
                    471: static void
                    472: convert_mbr_chs(cyl, head, sec, cylp, headp, secp, relsecs)
                    473:        int cyl, head, sec;
                    474:        u_int8_t *cylp, *headp, *secp;
                    475:        u_int32_t relsecs;
                    476: {
                    477:        unsigned int tcyl, temp, thead, tsec;
                    478:
                    479:        temp = head * sec;
                    480:        tcyl = relsecs / temp;
                    481:
                    482:        if (tcyl >= 1024) {
                    483:                *cylp = *headp = *secp = 0xff;
                    484:                return;
                    485:        }
                    486:
                    487:        relsecs %= temp;
                    488:        thead = relsecs / sec;
                    489:
                    490:        tsec = (relsecs % sec) + 1;
                    491:
                    492:        *cylp = MBR_PUT_LSCYL(tcyl);
                    493:        *headp = thead;
                    494:        *secp = MBR_PUT_MSCYLANDSEC(tcyl, tsec);
                    495: }
                    496:
                    497: /*
                    498:  * This function is ONLY to be used as a last resort to provide a
                    499:  * hint for the user. Ports should provide a more reliable way
                    500:  * of getting the BIOS geometry. The i386 code, for example,
                    501:  * uses the BIOS geometry as passed on from the bootblocks,
                    502:  * and only uses this as a hint to the user when that information
                    503:  * is not present, or a match could not be made with a NetBSD
                    504:  * device.
                    505:  */
                    506: int
                    507: guess_biosgeom_from_mbr(buf, cyl, head, sec)
                    508:        char *buf;
                    509:        int *cyl, *head, *sec;
                    510: {
                    511:        struct mbr_partition *parts = (struct mbr_partition *)&buf[MBR_PARTOFF];
                    512:        int cylinders = -1, heads = -1, sectors = -1, i, j;
                    513:        int c1, h1, s1, c2, h2, s2;
                    514:        long a1, a2;
                    515:        quad_t num, denom;
                    516:
                    517:        *cyl = *head = *sec = -1;
                    518:
                    519:        /* Try to deduce the number of heads from two different mappings. */
                    520:        for (i = 0; i < NMBRPART * 2; i++) {
                    521:                if (get_mapping(parts, i, &c1, &h1, &s1, &a1) < 0)
                    522:                        continue;
                    523:                for (j = 0; j < 8; j++) {
                    524:                        if (get_mapping(parts, j, &c2, &h2, &s2, &a2) < 0)
                    525:                                continue;
                    526:                        num = (quad_t)h1*(a2-s2) - (quad_t)h2*(a1-s1);
                    527:                        denom = (quad_t)c2*(a1-s1) - (quad_t)c1*(a2-s2);
                    528:                        if (denom != 0 && num % denom == 0) {
                    529:                                heads = num / denom;
                    530:                                break;
                    531:                        }
                    532:                }
                    533:                if (heads != -1)
                    534:                        break;
                    535:        }
                    536:
                    537:        if (heads == -1)
                    538:                return -1;
                    539:
                    540:        /* Now figure out the number of sectors from a single mapping. */
                    541:        for (i = 0; i < NMBRPART * 2; i++) {
                    542:                if (get_mapping(parts, i, &c1, &h1, &s1, &a1) < 0)
                    543:                        continue;
                    544:                num = a1 - s1;
                    545:                denom = c1 * heads + h1;
                    546:                if (denom != 0 && num % denom == 0) {
                    547:                        sectors = num / denom;
                    548:                        break;
                    549:                }
                    550:        }
                    551:
                    552:        if (sectors == -1)
                    553:                return -1;
                    554:
                    555:        /*
                    556:         * Estimate the number of cylinders.
                    557:         * XXX relies on get_disks having been called.
                    558:         */
                    559:        cylinders = disk->dd_totsec / heads / sectors;
                    560:
                    561:        /* Now verify consistency with each of the partition table entries.
                    562:         * Be willing to shove cylinders up a little bit to make things work,
                    563:         * but translation mismatches are fatal. */
                    564:        for (i = 0; i < NMBRPART * 2; i++) {
                    565:                if (get_mapping(parts, i, &c1, &h1, &s1, &a1) < 0)
                    566:                        continue;
                    567:                if (sectors * (c1 * heads + h1) + s1 != a1)
                    568:                        return -1;
                    569:                if (c1 >= cylinders)
                    570:                        cylinders = c1 + 1;
                    571:        }
                    572:
                    573:        /* Everything checks out.  Reset the geometry to use for further
                    574:         * calculations. */
                    575:        *cyl = cylinders;
                    576:        *head = heads;
                    577:        *sec = sectors;
                    578:        return 0;
                    579: }
                    580:
                    581: static int
                    582: get_mapping(parts, i, cylinder, head, sector, absolute)
                    583:        struct mbr_partition *parts;
                    584:        int i, *cylinder, *head, *sector;
                    585:        long *absolute;
                    586: {
                    587:        struct mbr_partition *part = &parts[i / 2];
                    588:
                    589:        if (part->mbrp_typ == 0)
                    590:                return -1;
                    591:        if (i % 2 == 0) {
                    592:                *cylinder = MBR_PCYL(part->mbrp_scyl, part->mbrp_ssect);
                    593:                *head = part->mbrp_shd;
                    594:                *sector = MBR_PSECT(part->mbrp_ssect) - 1;
                    595:                *absolute = part->mbrp_start;
                    596:        } else {
                    597:                *cylinder = MBR_PCYL(part->mbrp_ecyl, part->mbrp_esect);
                    598:                *head = part->mbrp_ehd;
                    599:                *sector = MBR_PSECT(part->mbrp_esect) - 1;
                    600:                *absolute = part->mbrp_start + part->mbrp_size - 1;
1.3       phil      601:        }
1.10      fvdl      602:        return 0;
1.1       phil      603: }

CVSweb <webmaster@jp.NetBSD.org>