[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.40

1.40    ! dsl         1: /*     $NetBSD: mbr.c,v 1.39 2003/06/13 11:57:29 dsl Exp $ */
1.1       phil        2:
                      3: /*
                      4:  * Copyright 1997 Piermont Information Systems Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Written by Philip A. Nelson for Piermont Information Systems Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
1.16      cgd        19:  *      This product includes software developed for the NetBSD Project by
1.1       phil       20:  *      Piermont Information Systems Inc.
                     21:  * 4. The name of Piermont Information Systems Inc. may not be used to endorse
                     22:  *    or promote products derived from this software without specific prior
                     23:  *    written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
                     26:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
                     29:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     35:  * THE POSSIBILITY OF SUCH DAMAGE.
                     36:  *
                     37:  */
                     38:
1.10      fvdl       39: /*
                     40:  * Following applies to the geometry guessing code
                     41:  */
                     42:
                     43: /*
                     44:  * Mach Operating System
                     45:  * Copyright (c) 1992 Carnegie Mellon University
                     46:  * All Rights Reserved.
                     47:  *
                     48:  * Permission to use, copy, modify and distribute this software and its
                     49:  * documentation is hereby granted, provided that both the copyright
                     50:  * notice and this permission notice appear in all copies of the
                     51:  * software, derivative works or modified versions, and any portions
                     52:  * thereof, and that both notices appear in supporting documentation.
                     53:  *
                     54:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     55:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     56:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     57:  *
                     58:  * Carnegie Mellon requests users of this software to return to
                     59:  *
                     60:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     61:  *  School of Computer Science
                     62:  *  Carnegie Mellon University
                     63:  *  Pittsburgh PA 15213-3890
                     64:  *
                     65:  * any improvements or extensions that they make and grant Carnegie Mellon
                     66:  * the rights to redistribute these changes.
                     67:  */
                     68:
1.6       jonathan   69: /* mbr.c -- DOS Master Boot Record editing code */
1.1       phil       70:
1.10      fvdl       71: #include <sys/param.h>
                     72: #include <sys/types.h>
1.1       phil       73: #include <stdio.h>
1.10      fvdl       74: #include <unistd.h>
                     75: #include <fcntl.h>
1.6       jonathan   76: #include <util.h>
1.1       phil       77: #include "defs.h"
1.10      fvdl       78: #include "mbr.h"
1.1       phil       79: #include "md.h"
                     80: #include "msg_defs.h"
                     81: #include "menu_defs.h"
1.10      fvdl       82: #include "endian.h"
1.1       phil       83:
                     84: struct part_id {
                     85:        int id;
                     86:        char *name;
                     87: } part_ids[] = {
                     88:        {0, "unused"},
1.20      soren      89:        {MBR_PTYPE_FAT12, "DOS FAT12"},
                     90:        {MBR_PTYPE_FAT16S, "DOS FAT16, <32M"},
                     91:        {MBR_PTYPE_EXT, "Extended partition"},
                     92:        {MBR_PTYPE_FAT16B, "DOS FAT16, >32M"},
1.10      fvdl       93:        {MBR_PTYPE_NTFS, "NTFS"},
1.20      soren      94:        {MBR_PTYPE_FAT32, "Windows FAT32"},
                     95:        {MBR_PTYPE_FAT32L, "Windows FAT32, LBA"},
                     96:        {MBR_PTYPE_FAT16L, "Windows FAT16, LBA"},
                     97:        {MBR_PTYPE_EXT_LBA, "Extended partition, LBA"},
1.10      fvdl       98:        {MBR_PTYPE_LNXSWAP, "Linux swap"},
                     99:        {MBR_PTYPE_LNXEXT2, "Linux native"},
1.20      soren     100:        {MBR_PTYPE_NTFSVOL, "NTFS volume set"},
1.10      fvdl      101:        {MBR_PTYPE_386BSD, "old NetBSD/FreeBSD/386BSD"},
                    102:        {MBR_PTYPE_NETBSD, "NetBSD"},
1.1       phil      103:        {-1, "Unknown"},
                    104: };
                    105:
1.10      fvdl      106: int dosptyp_nbsd = MBR_PTYPE_NETBSD;
                    107:
1.38      dsl       108: static int get_mapping(struct mbr_partition *, int, int *, int *, int *,
1.40    ! dsl       109:                            unsigned long *);
1.38      dsl       110: static void convert_mbr_chs(int, int, int, u_int8_t *, u_int8_t *,
1.25      mrg       111:                                 u_int8_t *, u_int32_t);
1.6       jonathan  112:
1.34      dsl       113: #ifdef BOOTSEL
                    114: static int defbootselpart, defbootseldisk;
                    115: struct mbr_bootsel *mbs;
                    116: #endif
1.6       jonathan  117:
                    118: /*
                    119:  * get C/H/S geometry from user via menu interface and
                    120:  * store in globals.
                    121:  */
1.7       mrg       122: void
1.38      dsl       123: set_bios_geom(int cyl, int head, int sec)
1.6       jonathan  124: {
                    125:        char res[80];
1.7       mrg       126:
1.6       jonathan  127:        msg_display_add(MSG_setbiosgeom);
1.10      fvdl      128:        snprintf(res, 80, "%d", cyl);
1.8       rvb       129:        msg_prompt_add(MSG_cylinders, res, res, 80);
1.6       jonathan  130:        bcyl = atoi(res);
1.8       rvb       131:
1.10      fvdl      132:        snprintf(res, 80, "%d", head);
1.8       rvb       133:        msg_prompt_add(MSG_heads, res, res, 80);
1.6       jonathan  134:        bhead = atoi(res);
1.8       rvb       135:
1.10      fvdl      136:        snprintf(res, 80, "%d", sec);
1.8       rvb       137:        msg_prompt_add(MSG_sectors, res, res, 80);
1.6       jonathan  138:        bsec = atoi(res);
                    139: }
                    140:
1.30      christos  141: #ifdef notdef
1.7       mrg       142: void
1.38      dsl       143: disp_cur_geom(void)
1.7       mrg       144: {
1.6       jonathan  145:
                    146:        msg_display_add(MSG_realgeom, dlcyl, dlhead, dlsec);
                    147:        msg_display_add(MSG_biosgeom, bcyl, bhead, bsec);
                    148: }
1.30      christos  149: #endif
1.6       jonathan  150:
                    151:
                    152: /*
                    153:  * Then,  the partition stuff...
                    154:  */
                    155: int
1.38      dsl       156: otherpart(int id)
1.6       jonathan  157: {
1.7       mrg       158:
1.10      fvdl      159:        return (id != 0 && id != MBR_PTYPE_386BSD && id != MBR_PTYPE_NETBSD);
1.6       jonathan  160: }
                    161:
                    162: int
1.38      dsl       163: ourpart(int id)
1.6       jonathan  164: {
1.7       mrg       165:
1.10      fvdl      166:        return (id == MBR_PTYPE_386BSD || id == MBR_PTYPE_NETBSD);
1.6       jonathan  167: }
                    168:
                    169: /*
                    170:  * Let user change incore Master Boot Record partitions via menu.
                    171:  */
1.7       mrg       172: int
1.38      dsl       173: edit_mbr(struct mbr_sector *mbr)
1.6       jonathan  174: {
                    175:        int i, j;
                    176:
                    177:        /* Ask full/part */
1.10      fvdl      178:
                    179:        /* XXX this sucks ("part" is used in menus, no param passing there) */
1.32      dsl       180:        part = &mbr->mbr_parts[0];
1.7       mrg       181:        msg_display(MSG_fullpart, diskdev);
1.37      dsl       182:        process_menu(MENU_fullpart, NULL);
1.6       jonathan  183:
                    184:        /* DOS fdisk label checking and value setting. */
                    185:        if (usefull) {
                    186:                int otherparts = 0;
                    187:                int ourparts = 0;
                    188:
                    189:                /* Count nonempty, non-BSD partitions. */
1.10      fvdl      190:                for (i = 0; i < NMBRPART; i++) {
1.14      bouyer    191:                        otherparts += otherpart(part[i].mbrp_typ);
1.6       jonathan  192:                        /* check for dualboot *bsd too */
1.14      bouyer    193:                        ourparts += ourpart(part[i].mbrp_typ);
1.6       jonathan  194:                }
                    195:
                    196:                /* Ask if we really want to blow away non-NetBSD stuff */
                    197:                if (otherparts != 0 || ourparts > 1) {
1.7       mrg       198:                        msg_display(MSG_ovrwrite);
1.37      dsl       199:                        process_menu(MENU_noyes, NULL);
1.6       jonathan  200:                        if (!yesno) {
1.9       garbled   201:                                if (logging)
1.29      fvdl      202:                                        (void)fprintf(logfp, "User answered no to destroy other data, aborting.\n");
1.6       jonathan  203:                                return 0;
                    204:                        }
                    205:                }
                    206:
                    207:                /* Set the partition information for full disk usage. */
1.14      bouyer    208:                part[0].mbrp_typ = part[0].mbrp_flag = 0;
                    209:                part[0].mbrp_start = part[0].mbrp_size = 0;
                    210:                part[1].mbrp_typ = part[0].mbrp_flag = 0;
                    211:                part[1].mbrp_start = part[0].mbrp_size = 0;
                    212:                part[2].mbrp_typ = part[0].mbrp_flag = 0;
                    213:                part[2].mbrp_start = part[0].mbrp_size = 0;
1.10      fvdl      214:                part[3].mbrp_typ = dosptyp_nbsd;
1.35      dsl       215:                part[3].mbrp_size = dlsize - bsec;
1.10      fvdl      216:                part[3].mbrp_start = bsec;
                    217:                part[3].mbrp_flag = 0x80;
1.6       jonathan  218:
                    219:                ptstart = bsec;
1.35      dsl       220:                ptsize = dlsize - bsec;
1.6       jonathan  221:                activepart = 3;
                    222:        } else {
                    223:                int numbsd, overlap;
                    224:                int numfreebsd, freebsdpart;    /* dual-boot */
                    225:
                    226:                /* Ask for sizes, which partitions, ... */
1.21      fvdl      227:                ask_sizemult(bcylsize);
1.6       jonathan  228:                bsdpart = freebsdpart = -1;
                    229:                activepart = -1;
1.35      dsl       230:                for (i = 0; i < NMBRPART; i++) {
1.13      bouyer    231:                        if (part[i].mbrp_flag != 0) {
1.6       jonathan  232:                                activepart = i;
1.13      bouyer    233:                                part[i].mbrp_flag = 0;
                    234:                        }
1.35      dsl       235:                }
1.6       jonathan  236:                do {
1.37      dsl       237:                        process_menu(MENU_editparttable, NULL);
1.6       jonathan  238:                        numbsd = 0;
                    239:                        bsdpart = -1;
                    240:                        freebsdpart = -1;
                    241:                        numfreebsd = 0;
                    242:                        overlap = 0;
                    243:                        yesno = 0;
1.33      dsl       244:                        for (i=0; i < NMBRPART; i++) {
1.7       mrg       245:                                /* Count 386bsd/FreeBSD/NetBSD(old) partitions */
1.10      fvdl      246:                                if (part[i].mbrp_typ == MBR_PTYPE_386BSD) {
1.6       jonathan  247:                                        freebsdpart = i;
                    248:                                        numfreebsd++;
                    249:                                }
                    250:                                /* Count NetBSD-only partitions */
1.10      fvdl      251:                                if (part[i].mbrp_typ == MBR_PTYPE_NETBSD) {
1.33      dsl       252:                                        if (bsdpart == -1)
                    253:                                                bsdpart = i;
1.6       jonathan  254:                                        numbsd++;
                    255:                                }
1.33      dsl       256:                                for (j = i + 1; j < NMBRPART; j++)
                    257:                                       if (partsoverlap(part, i, j))
1.6       jonathan  258:                                               overlap = 1;
                    259:                        }
                    260:
                    261:                        /* If no new-NetBSD partition, use 386bsd instead */
                    262:                        if (numbsd == 0 && numfreebsd > 0) {
                    263:                                numbsd = numfreebsd;
                    264:                                bsdpart = freebsdpart;
                    265:                                /* XXX check partition type? */
                    266:                        }
                    267:
                    268:                        /* Check for overlap or multiple native partitions */
                    269:                        if (overlap || numbsd != 1) {
1.7       mrg       270:                                msg_display(MSG_reeditpart);
1.37      dsl       271:                                process_menu(MENU_yesno, NULL);
1.6       jonathan  272:                        }
                    273:                } while (yesno && (numbsd != 1 || overlap));
1.11      fvdl      274:
1.6       jonathan  275:
                    276:                if (numbsd == 0) {
1.7       mrg       277:                        msg_display(MSG_nobsdpart);
1.37      dsl       278:                        process_menu(MENU_ok, NULL);
1.6       jonathan  279:                        return 0;
                    280:                }
                    281:
                    282:                if (numbsd > 1) {
1.7       mrg       283:                        msg_display(MSG_multbsdpart, bsdpart);
1.37      dsl       284:                        process_menu(MENU_ok, NULL);
1.6       jonathan  285:                }
1.15      fvdl      286:
                    287:                if (activepart == -1) {
                    288:                        msg_display(MSG_noactivepart);
1.37      dsl       289:                        process_menu(MENU_yesno, NULL);
1.15      fvdl      290:                        if (yesno)
                    291:                                part[bsdpart].mbrp_flag = 0x80;
                    292:                } else
                    293:                        part[activepart].mbrp_flag = 0x80;
                    294:
                    295:                if (bsdpart == freebsdpart) {
                    296:                        msg_display(MSG_upgradeparttype);
1.37      dsl       297:                        process_menu(MENU_yesno, NULL);
1.15      fvdl      298:                        if (yesno)
                    299:                                part[bsdpart].mbrp_typ = dosptyp_nbsd;
                    300:                }
1.6       jonathan  301:
1.10      fvdl      302:                ptstart = part[bsdpart].mbrp_start;
                    303:                ptsize = part[bsdpart].mbrp_size;
1.6       jonathan  304:
                    305:                /* Ask if a boot selector is wanted. XXXX */
                    306:        }
                    307:
                    308:        return 1;
                    309: }
                    310:
1.33      dsl       311: void
                    312: edit_ptn_bounds(void)
                    313: {
                    314:        char buf[40]; int start, size, inp, partn;
                    315:
                    316:        msg_table_add(MSG_mbrpart_start_special);
                    317:        msg_prompt_add(MSG_start, NULL, buf, sizeof buf);
                    318:        inp = atoi(buf);
                    319:        /*
                    320:         * -0, -1, -2, -3: start at end of part # given
                    321:         * 0: start of disk.
                    322:         */
                    323:        if ((inp == 0 && buf[0] == '-') || (inp < 0 && inp >= -3)) {
                    324:                partn = -inp;
                    325:                start = part[partn].mbrp_start + part[partn].mbrp_size;
                    326:        } else if (inp == 0)
                    327:                start = bsec;
                    328:        else
                    329:                start = NUMSEC(inp, sizemult, dlcylsize);
                    330:
                    331:        if (sizemult > 1 && start < bsec)
                    332:                start = bsec;
                    333:        msg_table_add(MSG_mbrpart_size_special);
1.38      dsl       334:        msg_prompt_add(MSG_size, NULL, buf, 40);
1.33      dsl       335:        inp = atoi(buf);
                    336:        /*
                    337:         * -0, -1, -2, -3: until start of part # given
                    338:         * 0: end of disk
                    339:         */
                    340:        if ((inp == 0 && buf[0] == '-') || (inp < 0 && inp >= -3)) {
                    341:                partn = -inp;
                    342:                size = part[partn].mbrp_start - start;
                    343:        } else if (inp == 0)
                    344:                size = dlsize - start;
                    345:        else
                    346:                size = NUMSEC(inp, sizemult, dlcylsize);
                    347:        if (sizemult > 1 && start == bsec)
                    348:                size -= bsec;
1.35      dsl       349:        if (start + size > dlsize)
                    350:                size = dlsize - start;
1.33      dsl       351:        if (size < 0) {
                    352:                size = 0;
                    353:                start = 0;
                    354:        }
                    355:        part[editpart].mbrp_start = start;
                    356:        part[editpart].mbrp_size = size;
                    357: }
                    358:
1.7       mrg       359: int
1.38      dsl       360: partsoverlap(struct mbr_partition *part, int i, int j)
1.1       phil      361: {
1.7       mrg       362:
1.28      mrg       363:        /*
                    364:         * If the size or type of either partition is zero, they don't
                    365:         * overlap by definition.
                    366:         */
                    367:        if (part[i].mbrp_size == 0 || part[j].mbrp_size == 0 ||
                    368:            part[i].mbrp_typ == 0 || part[j].mbrp_typ == 0)
1.1       phil      369:                return 0;
                    370:
1.2       phil      371:        return
1.10      fvdl      372:                (part[i].mbrp_start < part[j].mbrp_start &&
                    373:                 part[i].mbrp_start + part[i].mbrp_size > part[j].mbrp_start)
1.1       phil      374:                ||
1.10      fvdl      375:                (part[i].mbrp_start > part[j].mbrp_start &&
                    376:                 part[i].mbrp_start < part[j].mbrp_start + part[j].mbrp_size)
1.1       phil      377:                ||
1.10      fvdl      378:                (part[i].mbrp_start == part[j].mbrp_start);
1.1       phil      379: }
                    380:
1.15      fvdl      381: char *
1.38      dsl       382: get_partname(int i)
1.15      fvdl      383: {
                    384:        int j;
1.34      dsl       385:        static char unknown[32];
1.15      fvdl      386:
1.34      dsl       387:        for (j = 0; part_ids[j].id != -1; j++)
                    388:                if (part_ids[j].id == part[i].mbrp_typ)
                    389:                        return part_ids[j].name;
1.15      fvdl      390:
1.34      dsl       391:        snprintf(unknown, sizeof unknown, "Unknown (%d)", part[i].mbrp_typ);
                    392:        return unknown;
1.15      fvdl      393: }
                    394:
1.7       mrg       395: void
1.38      dsl       396: disp_cur_part(struct mbr_partition *part, int sel, int disp)
1.1       phil      397: {
1.15      fvdl      398:        int i, start, stop, rsize, rend;
1.1       phil      399:
                    400:        if (disp < 0)
                    401:                start = 0, stop = 4;
                    402:        else
                    403:                start = disp, stop = disp+1;
1.23      fvdl      404:        msg_table_add(MSG_part_header, dlsize/sizemult, multname, multname,
                    405:            multname, multname);
1.7       mrg       406:        for (i = start; i < stop; i++) {
                    407:                if (sel == i)
                    408:                        msg_standout();
1.23      fvdl      409:                if (part[i].mbrp_typ == 0 ||
                    410:                    (part[i].mbrp_size == 0 && part[i].mbrp_start == 0))
1.17      cgd       411:                        msg_table_add(MSG_part_row_start_unused, i);
1.4       fvdl      412:                else {
1.10      fvdl      413:                        rsize = part[i].mbrp_size / sizemult;
                    414:                        if (part[i].mbrp_size % sizemult)
1.4       fvdl      415:                                rsize++;
1.10      fvdl      416:                        rend = (part[i].mbrp_start + part[i].mbrp_size) / sizemult;
1.24      hubertf   417:                        if ((part[i].mbrp_start + part[i].mbrp_size) % sizemult)
1.4       fvdl      418:                                rend++;
1.17      cgd       419:                        msg_table_add(MSG_part_row_start_used, i,
1.27      grant     420:                            part[i].mbrp_start / sizemult, rend, rsize);
1.4       fvdl      421:                }
1.17      cgd       422:                msg_table_add(MSG_part_row_end, get_partname(i));
1.10      fvdl      423:                if (sel == i)
                    424:                        msg_standend();
                    425:        }
                    426: }
                    427:
                    428: int
1.38      dsl       429: read_mbr(const char *disk, mbr_sector_t *mbr, size_t len)
1.10      fvdl      430: {
                    431:        char diskpath[MAXPATHLEN];
                    432:        int fd, i;
                    433:        struct mbr_partition *mbrp;
                    434:
                    435:        /* Open the disk. */
                    436:        fd = opendisk(disk, O_RDONLY, diskpath, sizeof(diskpath), 0);
                    437:        if (fd < 0)
                    438:                return -1;
                    439:
1.30      christos  440:        if (lseek(fd, (off_t)(MBR_BBSECTOR * MBR_SECSIZE), SEEK_SET) < 0) {
1.10      fvdl      441:                close(fd);
                    442:                return -1;
                    443:        }
1.32      dsl       444:        if (read(fd, mbr, len) < len) {
1.10      fvdl      445:                close(fd);
                    446:                return -1;
                    447:        }
                    448:
1.32      dsl       449:        if (valid_mbr(mbr)) {
                    450:                mbrp = &mbr->mbr_parts[0];
1.10      fvdl      451:                for (i = 0; i < NMBRPART; i++) {
                    452:                        if (mbrp[i].mbrp_typ != 0) {
                    453:                                mbrp[i].mbrp_start =
                    454:                                    le_to_native32(mbrp[i].mbrp_start);
                    455:                                mbrp[i].mbrp_size =
                    456:                                    le_to_native32(mbrp[i].mbrp_size);
1.26      mrg       457:                        } else {
                    458:                                /* type is unused, discard scum */
                    459:                                mbrp[i].mbrp_start = 0;
                    460:                                mbrp[i].mbrp_size  = 0;
1.10      fvdl      461:                        }
                    462:                }
                    463:        }
                    464:
                    465:        (void)close(fd);
                    466:        return 0;
                    467: }
                    468:
                    469: int
1.38      dsl       470: write_mbr(const char *disk, mbr_sector_t *mbr, size_t len, int convert)
1.10      fvdl      471: {
                    472:        char diskpath[MAXPATHLEN];
                    473:        int fd, i, ret = 0;
                    474:        struct mbr_partition *mbrp;
                    475:        u_int32_t pstart, psize;
                    476:
                    477:        /* Open the disk. */
                    478:        fd = opendisk(disk, O_WRONLY, diskpath, sizeof(diskpath), 0);
                    479:        if (fd < 0)
                    480:                return -1;
                    481:
1.30      christos  482:        if (lseek(fd, (off_t)(MBR_BBSECTOR * MBR_SECSIZE), SEEK_SET) < 0) {
1.10      fvdl      483:                close(fd);
                    484:                return -1;
                    485:        }
                    486:
1.32      dsl       487:        mbrp = &mbr->mbr_parts[0];
1.10      fvdl      488:        for (i = 0; i < NMBRPART; i++) {
1.14      bouyer    489:                if (mbrp[i].mbrp_start == 0 &&
                    490:                    mbrp[i].mbrp_size == 0) {
                    491:                        mbrp[i].mbrp_scyl = 0;
                    492:                        mbrp[i].mbrp_shd = 0;
                    493:                        mbrp[i].mbrp_ssect = 0;
                    494:                        mbrp[i].mbrp_ecyl = 0;
                    495:                        mbrp[i].mbrp_ehd = 0;
                    496:                        mbrp[i].mbrp_esect = 0;
                    497:                } else {
1.10      fvdl      498:                        pstart = mbrp[i].mbrp_start;
                    499:                        psize = mbrp[i].mbrp_size;
                    500:                        mbrp[i].mbrp_start = native_to_le32(pstart);
                    501:                        mbrp[i].mbrp_size = native_to_le32(psize);
1.18      fvdl      502:                        if (convert) {
                    503:                                convert_mbr_chs(bcyl, bhead, bsec,
                    504:                                    &mbrp[i].mbrp_scyl, &mbrp[i].mbrp_shd,
                    505:                                    &mbrp[i].mbrp_ssect, pstart);
                    506:                                convert_mbr_chs(bcyl, bhead, bsec,
                    507:                                    &mbrp[i].mbrp_ecyl, &mbrp[i].mbrp_ehd,
1.19      fvdl      508:                                    &mbrp[i].mbrp_esect, pstart + psize - 1);
1.18      fvdl      509:                        }
1.10      fvdl      510:                }
                    511:        }
                    512:
1.32      dsl       513:        if (write(fd, mbr, len) < 0)
1.10      fvdl      514:                ret = -1;
                    515:
                    516:        (void)close(fd);
                    517:        return ret;
                    518: }
                    519:
                    520: int
1.38      dsl       521: valid_mbr(mbr_sector_t *mbr)
1.10      fvdl      522: {
                    523:
1.32      dsl       524:        return (le_to_native16(mbr->mbr_signature) == MBR_MAGIC);
1.10      fvdl      525: }
                    526:
                    527: static void
1.38      dsl       528: convert_mbr_chs(int cyl, int head, int sec,
                    529:                u_int8_t *cylp, u_int8_t *headp, u_int8_t *secp,
                    530:                u_int32_t relsecs)
1.10      fvdl      531: {
                    532:        unsigned int tcyl, temp, thead, tsec;
                    533:
1.22      fvdl      534:        temp = cyl * head * sec - 1;
                    535:        if (relsecs >= temp)
                    536:                relsecs = temp;
                    537:
1.10      fvdl      538:        temp = head * sec;
                    539:        tcyl = relsecs / temp;
                    540:
                    541:        relsecs %= temp;
                    542:        thead = relsecs / sec;
                    543:
                    544:        tsec = (relsecs % sec) + 1;
                    545:
                    546:        *cylp = MBR_PUT_LSCYL(tcyl);
                    547:        *headp = thead;
                    548:        *secp = MBR_PUT_MSCYLANDSEC(tcyl, tsec);
                    549: }
                    550:
                    551: /*
                    552:  * This function is ONLY to be used as a last resort to provide a
                    553:  * hint for the user. Ports should provide a more reliable way
                    554:  * of getting the BIOS geometry. The i386 code, for example,
                    555:  * uses the BIOS geometry as passed on from the bootblocks,
                    556:  * and only uses this as a hint to the user when that information
                    557:  * is not present, or a match could not be made with a NetBSD
                    558:  * device.
                    559:  */
1.40    ! dsl       560:
        !           561: #define MAXCYL         1023    /* Possibly 1024 */
        !           562: #define MAXHEAD                255     /* Possibly 256 */
        !           563: #define MAXSECTOR      63
        !           564:
1.10      fvdl      565: int
1.38      dsl       566: guess_biosgeom_from_mbr(mbr_sector_t *mbr, int *cyl, int *head, int *sec)
1.10      fvdl      567: {
1.32      dsl       568:        struct mbr_partition *parts = &mbr->mbr_parts[0];
1.40    ! dsl       569:        int xcylinders, xheads, xsectors, i, j;
1.10      fvdl      570:        int c1, h1, s1, c2, h2, s2;
1.40    ! dsl       571:        unsigned long a1, a2;
        !           572:        uint64_t num, denom;
        !           573:
        !           574:        /*
        !           575:         * The physical parameters may be invalid as bios geometry.
        !           576:         * If we cannot determine the actual bios geometry, we are
        !           577:         * better off picking a likely 'faked' geometry than leaving
        !           578:         * the invalid physical one.
        !           579:         */
1.10      fvdl      580:
1.40    ! dsl       581:        xcylinders = dlcyl;
        !           582:        xheads = dlhead;
        !           583:        xsectors = dlsec;
        !           584:        if (xcylinders > MAXCYL || xheads > MAXHEAD || xsectors > MAXSECTOR) {
        !           585:                xsectors = MAXSECTOR;
        !           586:                xheads = MAXHEAD;
        !           587:                xcylinders = disk->dd_totsec / (MAXSECTOR * MAXHEAD);
        !           588:                if (xcylinders > MAXCYL)
        !           589:                        xcylinders = MAXCYL;
        !           590:        }
        !           591:        *cyl = xcylinders;
        !           592:        *head = xheads;
        !           593:        *sec = xsectors;
        !           594:
        !           595:        xheads = -1;
1.10      fvdl      596:
                    597:        /* Try to deduce the number of heads from two different mappings. */
1.40    ! dsl       598:        for (i = 0; i < NMBRPART * 2 - 1; i++) {
1.10      fvdl      599:                if (get_mapping(parts, i, &c1, &h1, &s1, &a1) < 0)
                    600:                        continue;
1.40    ! dsl       601:                for (j = i + 1; j < NMBRPART * 2; j++) {
1.10      fvdl      602:                        if (get_mapping(parts, j, &c2, &h2, &s2, &a2) < 0)
                    603:                                continue;
1.40    ! dsl       604:                        a1 -= s1;
        !           605:                        a2 -= s2;
        !           606:                        num = (uint64_t)h1 * a2 - (quad_t)h2 * a1;
        !           607:                        denom = (uint64_t)c2 * a1 - (quad_t)c1 * a2;
1.10      fvdl      608:                        if (denom != 0 && num % denom == 0) {
1.40    ! dsl       609:                                xheads = (int)(num / denom);
        !           610:                                xsectors = a1 / (c1 * xheads + h1);
1.10      fvdl      611:                                break;
                    612:                        }
                    613:                }
1.40    ! dsl       614:                if (xheads != -1)
1.10      fvdl      615:                        break;
                    616:        }
                    617:
1.40    ! dsl       618:        if (xheads == -1)
1.10      fvdl      619:                return -1;
                    620:
                    621:        /*
                    622:         * Estimate the number of cylinders.
                    623:         * XXX relies on get_disks having been called.
                    624:         */
1.40    ! dsl       625:        xcylinders = disk->dd_totsec / xheads / xsectors;
1.10      fvdl      626:
                    627:        /* Now verify consistency with each of the partition table entries.
                    628:         * Be willing to shove cylinders up a little bit to make things work,
                    629:         * but translation mismatches are fatal. */
                    630:        for (i = 0; i < NMBRPART * 2; i++) {
                    631:                if (get_mapping(parts, i, &c1, &h1, &s1, &a1) < 0)
                    632:                        continue;
1.40    ! dsl       633:                if (xsectors * (c1 * xheads + h1) + s1 != a1)
1.10      fvdl      634:                        return -1;
1.40    ! dsl       635:                if (c1 >= xcylinders)
        !           636:                        xcylinders = c1 + 1;
1.10      fvdl      637:        }
                    638:
1.40    ! dsl       639:        /*
        !           640:         * Everything checks out.  Reset the geometry to use for further
        !           641:         * calculations.
        !           642:         */
        !           643:        *cyl = MIN(xcylinders, MAXCYL);
        !           644:        *head = xheads;
        !           645:        *sec = xsectors;
1.10      fvdl      646:        return 0;
                    647: }
                    648:
                    649: static int
1.38      dsl       650: get_mapping(mbr_partition_t *parts, int i,
1.40    ! dsl       651:            int *cylinder, int *head, int *sector, unsigned long *absolute)
1.10      fvdl      652: {
1.30      christos  653:        struct mbr_partition *apart = &parts[i / 2];
1.10      fvdl      654:
1.30      christos  655:        if (apart->mbrp_typ == 0)
1.10      fvdl      656:                return -1;
                    657:        if (i % 2 == 0) {
1.31      shin      658:                *cylinder = MBR_PCYL(apart->mbrp_scyl, apart->mbrp_ssect);
1.30      christos  659:                *head = apart->mbrp_shd;
                    660:                *sector = MBR_PSECT(apart->mbrp_ssect) - 1;
1.40    ! dsl       661:                *absolute = le32toh(apart->mbrp_start);
1.10      fvdl      662:        } else {
1.30      christos  663:                *cylinder = MBR_PCYL(apart->mbrp_ecyl, apart->mbrp_esect);
                    664:                *head = apart->mbrp_ehd;
                    665:                *sector = MBR_PSECT(apart->mbrp_esect) - 1;
1.40    ! dsl       666:                *absolute = le32toh(apart->mbrp_start)
        !           667:                        + le32toh(apart->mbrp_size) - 1;
1.3       phil      668:        }
1.40    ! dsl       669:        /* Sanity check the data against max values */
        !           670:        if ((((*cylinder * MAXHEAD) + *head) * MAXSECTOR + *sector) < *absolute)
        !           671:                /* cannot be a CHS mapping */
        !           672:                return -1;
        !           673:
1.10      fvdl      674:        return 0;
1.1       phil      675: }
1.33      dsl       676:
                    677: #ifdef BOOTSEL
                    678:
                    679: void
                    680: disp_bootsel(void)
                    681: {
                    682:        int i;
                    683:
                    684:        msg_display(MSG_configbootsel);
                    685:        msg_table_add(MSG_bootsel_header);
1.34      dsl       686:        for (i = 0; i < NMBRPART; i++) {
1.33      dsl       687:                msg_table_add(MSG_bootsel_row, i, get_partname(i),
                    688:                        mbs->mbrb_nametab[i]);
                    689:        }
                    690:        msg_display_add(MSG_newline);
                    691:
                    692:        msg_display_add(MSG_bootseltimeout, (10 * mbs->mbrb_timeo + 9) / 182);
                    693:        msg_display_add(MSG_defbootselopt);
                    694:        if (mbs->mbrb_defkey == SCAN_ENTER)
                    695:                msg_display_add(MSG_defbootseloptactive);
1.34      dsl       696:        else if (mbs->mbrb_defkey < (SCAN_1 + 10))
1.33      dsl       697:                msg_display_add(MSG_defbootseloptpart, defbootselpart);
                    698:        else
                    699:                msg_display_add(MSG_defbootseloptdisk, defbootseldisk);
                    700: }
                    701:
                    702: void
                    703: edit_bootsel_entry(int ptn)
                    704: {
1.38      dsl       705:
1.33      dsl       706:        if (part[ptn].mbrp_typ != 0)
                    707:                msg_prompt(MSG_bootselitemname, mbs->mbrb_nametab[ptn],
                    708:                            mbs->mbrb_nametab[ptn], 8);
                    709: }
                    710:
                    711: void
                    712: edit_bootsel_timeout(void)
                    713: {
                    714:        char tstr[8];
                    715:        unsigned timo;
                    716:
                    717:        do {
                    718:                snprintf(tstr, 8, "%u", (10 * mbs->mbrb_timeo + 9) / 182);
                    719:                msg_prompt(MSG_bootseltimeoutval, tstr, tstr, 8);
                    720:                timo = (unsigned)atoi(tstr);
                    721:        } while (timo > 3600);
                    722:        mbs->mbrb_timeo = (u_int16_t)((timo * 182) / 10);
                    723: }
                    724:
                    725: void
                    726: edit_bootsel_default_ptn(int ptn)
                    727: {
                    728:        int i;
                    729:        int key = SCAN_1;
                    730:
                    731:        if (mbs->mbrb_nametab[ptn][0] == 0 || part[ptn].mbrp_typ == 0)
                    732:                return;
                    733:        for (i = 0; i < ptn; i++)
                    734:                if (mbs->mbrb_nametab[i][0] != 0 && part[i].mbrp_typ != 0)
                    735:                        key++;
                    736:        mbs->mbrb_defkey = key;
                    737:        defbootselpart = ptn;
                    738: }
                    739:
                    740: void
                    741: edit_bootsel_default_disk(int disk)
                    742: {
                    743:
                    744:        mbs->mbrb_defkey = SCAN_F1 + disk;
                    745:        defbootseldisk = disk;
                    746: }
1.34      dsl       747:
                    748: void
                    749: configure_bootsel(void)
                    750: {
                    751:        struct mbr_partition *parts = &mbr.mbr_parts[0];
                    752:        int i;
                    753:        const char *name, *cp;
                    754:
                    755:        mbs = &mbr.mbr_bootsel;
                    756:
                    757:        /*
                    758:         * Setup default labels for partitions, since if not done by user
                    759:         * they don't get set and bootselector doesn't 'appear' when
                    760:         * it's loaded.
                    761:         */
1.36      dsl       762:        for (i = 0; i < NMBRPART; i++) {
                    763:                if (parts[i].mbrp_typ == 0 ||
                    764:                    parts[i].mbrp_typ == MBR_PTYPE_LNXSWAP ||
                    765:                    MBR_IS_EXTENDED(parts[i].mbrp_typ))
                    766:                        mbs->mbrb_nametab[i][0] = 0;
                    767:        }
                    768:
1.34      dsl       769:        for (i = 0; i < NMBRPART; i++) {
                    770:                if (parts[i].mbrp_typ == MBR_PTYPE_NETBSD &&
                    771:                    mbs->mbrb_nametab[i][0] != 0)
                    772:                        goto labels_ok;
                    773:        }
                    774:
                    775:        for (i = 0; i < NMBRPART; i++) {
                    776:                if (parts[i].mbrp_typ == 0 ||
                    777:                    parts[i].mbrp_typ == MBR_PTYPE_LNXSWAP ||
                    778:                    MBR_IS_EXTENDED(parts[i].mbrp_typ) ||
                    779:                    mbs->mbrb_nametab[i][0] != '\0')
                    780:                        continue;
                    781:                /* Default to first word of partition name */
                    782:                name = get_partname(i);
                    783:                cp = strchr(name, ' ');
                    784:                snprintf(mbs->mbrb_nametab[i], sizeof(mbs->mbrb_nametab[0]),
                    785:                         "%.*s", cp != NULL ? cp - name : 256, name);
                    786:        }
                    787:
                    788:     labels_ok:
1.37      dsl       789:        process_menu(MENU_configbootsel, NULL);
1.34      dsl       790:
                    791: #if 0
                    792:        /* The current bootselect code doesn't need this... */
                    793:        mbs->mbrb_flags &= ~BFL_EXTINT13;
                    794:        for (i = 0; i < NMBRPART; i++) {
                    795:                if (parts[i].mbrp_typ != 0 &&
                    796:                   parts[i].mbrp_start >= (bcyl * bhead * bsec)) {
                    797:                        mbs->mbrb_flags |= BFL_EXTINT13;
                    798:                        break;
                    799:                }
                    800:        }
                    801: #endif
                    802: }
                    803:
1.33      dsl       804: #endif

CVSweb <webmaster@jp.NetBSD.org>