NetBSD/distrib/utils/sysinst/mbr.c
dsl 17ae477780 Implement a limit on the size of / so that its guaranteed readable by the boot code.
Remove pointless 'len' parameter from read_mbr and write_mbr.
Make read_mbr initialise mbr if it can't be read (delete MD code).
Make i386 always ask at least once about the bootcode.
Move LIB_MOVE and LIB_COUNT from md.h to aout2elf.c
2003-06-14 12:58:45 +00:00

802 lines
20 KiB
C

/* $NetBSD: mbr.c,v 1.41 2003/06/14 12:58:45 dsl Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
*
* Written by Philip A. Nelson for Piermont Information Systems Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Piermont Information Systems Inc.
* 4. The name of Piermont Information Systems Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* Following applies to the geometry guessing code
*/
/*
* Mach Operating System
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/* mbr.c -- DOS Master Boot Record editing code */
#include <sys/param.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <util.h>
#include "defs.h"
#include "mbr.h"
#include "md.h"
#include "msg_defs.h"
#include "menu_defs.h"
#include "endian.h"
struct part_id {
int id;
char *name;
} part_ids[] = {
{0, "unused"},
{MBR_PTYPE_FAT12, "DOS FAT12"},
{MBR_PTYPE_FAT16S, "DOS FAT16, <32M"},
{MBR_PTYPE_EXT, "Extended partition"},
{MBR_PTYPE_FAT16B, "DOS FAT16, >32M"},
{MBR_PTYPE_NTFS, "NTFS"},
{MBR_PTYPE_FAT32, "Windows FAT32"},
{MBR_PTYPE_FAT32L, "Windows FAT32, LBA"},
{MBR_PTYPE_FAT16L, "Windows FAT16, LBA"},
{MBR_PTYPE_EXT_LBA, "Extended partition, LBA"},
{MBR_PTYPE_LNXSWAP, "Linux swap"},
{MBR_PTYPE_LNXEXT2, "Linux native"},
{MBR_PTYPE_NTFSVOL, "NTFS volume set"},
{MBR_PTYPE_386BSD, "old NetBSD/FreeBSD/386BSD"},
{MBR_PTYPE_NETBSD, "NetBSD"},
{-1, "Unknown"},
};
int dosptyp_nbsd = MBR_PTYPE_NETBSD;
static int get_mapping(struct mbr_partition *, int, int *, int *, int *,
unsigned long *);
static void convert_mbr_chs(int, int, int, u_int8_t *, u_int8_t *,
u_int8_t *, u_int32_t);
#ifdef BOOTSEL
static int defbootselpart, defbootseldisk;
struct mbr_bootsel *mbs;
#endif
/*
* get C/H/S geometry from user via menu interface and
* store in globals.
*/
void
set_bios_geom(int cyl, int head, int sec)
{
char res[80];
msg_display_add(MSG_setbiosgeom);
snprintf(res, 80, "%d", cyl);
msg_prompt_add(MSG_cylinders, res, res, 80);
bcyl = atoi(res);
snprintf(res, 80, "%d", head);
msg_prompt_add(MSG_heads, res, res, 80);
bhead = atoi(res);
snprintf(res, 80, "%d", sec);
msg_prompt_add(MSG_sectors, res, res, 80);
bsec = atoi(res);
}
#ifdef notdef
void
disp_cur_geom(void)
{
msg_display_add(MSG_realgeom, dlcyl, dlhead, dlsec);
msg_display_add(MSG_biosgeom, bcyl, bhead, bsec);
}
#endif
/*
* Then, the partition stuff...
*/
int
otherpart(int id)
{
return (id != 0 && id != MBR_PTYPE_386BSD && id != MBR_PTYPE_NETBSD);
}
int
ourpart(int id)
{
return (id == MBR_PTYPE_386BSD || id == MBR_PTYPE_NETBSD);
}
/*
* Let user change incore Master Boot Record partitions via menu.
*/
int
edit_mbr(struct mbr_sector *mbr)
{
int i, j;
/* Ask full/part */
/* XXX this sucks ("part" is used in menus, no param passing there) */
part = &mbr->mbr_parts[0];
msg_display(MSG_fullpart, diskdev);
process_menu(MENU_fullpart, NULL);
/* DOS fdisk label checking and value setting. */
if (usefull) {
int otherparts = 0;
int ourparts = 0;
/* Count nonempty, non-BSD partitions. */
for (i = 0; i < NMBRPART; i++) {
otherparts += otherpart(part[i].mbrp_typ);
/* check for dualboot *bsd too */
ourparts += ourpart(part[i].mbrp_typ);
}
/* Ask if we really want to blow away non-NetBSD stuff */
if (otherparts != 0 || ourparts > 1) {
msg_display(MSG_ovrwrite);
process_menu(MENU_noyes, NULL);
if (!yesno) {
if (logging)
(void)fprintf(logfp, "User answered no to destroy other data, aborting.\n");
return 0;
}
}
/* Set the partition information for full disk usage. */
part[0].mbrp_typ = part[0].mbrp_flag = 0;
part[0].mbrp_start = part[0].mbrp_size = 0;
part[1].mbrp_typ = part[0].mbrp_flag = 0;
part[1].mbrp_start = part[0].mbrp_size = 0;
part[2].mbrp_typ = part[0].mbrp_flag = 0;
part[2].mbrp_start = part[0].mbrp_size = 0;
part[3].mbrp_typ = dosptyp_nbsd;
part[3].mbrp_size = dlsize - bsec;
part[3].mbrp_start = bsec;
part[3].mbrp_flag = 0x80;
ptstart = bsec;
ptsize = dlsize - bsec;
activepart = 3;
} else {
int numbsd, overlap;
int numfreebsd, freebsdpart; /* dual-boot */
/* Ask for sizes, which partitions, ... */
ask_sizemult(bcylsize);
bsdpart = freebsdpart = -1;
activepart = -1;
for (i = 0; i < NMBRPART; i++) {
if (part[i].mbrp_flag != 0) {
activepart = i;
part[i].mbrp_flag = 0;
}
}
do {
process_menu(MENU_editparttable, NULL);
numbsd = 0;
bsdpart = -1;
freebsdpart = -1;
numfreebsd = 0;
overlap = 0;
yesno = 0;
for (i=0; i < NMBRPART; i++) {
/* Count 386bsd/FreeBSD/NetBSD(old) partitions */
if (part[i].mbrp_typ == MBR_PTYPE_386BSD) {
freebsdpart = i;
numfreebsd++;
}
/* Count NetBSD-only partitions */
if (part[i].mbrp_typ == MBR_PTYPE_NETBSD) {
if (bsdpart == -1)
bsdpart = i;
numbsd++;
}
for (j = i + 1; j < NMBRPART; j++)
if (partsoverlap(part, i, j))
overlap = 1;
}
/* If no new-NetBSD partition, use 386bsd instead */
if (numbsd == 0 && numfreebsd > 0) {
numbsd = numfreebsd;
bsdpart = freebsdpart;
/* XXX check partition type? */
}
/* Check for overlap or multiple native partitions */
if (overlap || numbsd != 1) {
msg_display(MSG_reeditpart);
process_menu(MENU_yesno, NULL);
}
} while (yesno && (numbsd != 1 || overlap));
if (numbsd == 0) {
msg_display(MSG_nobsdpart);
process_menu(MENU_ok, NULL);
return 0;
}
if (numbsd > 1) {
msg_display(MSG_multbsdpart, bsdpart);
process_menu(MENU_ok, NULL);
}
if (activepart == -1) {
msg_display(MSG_noactivepart);
process_menu(MENU_yesno, NULL);
if (yesno)
part[bsdpart].mbrp_flag = 0x80;
} else
part[activepart].mbrp_flag = 0x80;
if (bsdpart == freebsdpart) {
msg_display(MSG_upgradeparttype);
process_menu(MENU_yesno, NULL);
if (yesno)
part[bsdpart].mbrp_typ = dosptyp_nbsd;
}
ptstart = part[bsdpart].mbrp_start;
ptsize = part[bsdpart].mbrp_size;
/* Ask if a boot selector is wanted. XXXX */
}
return 1;
}
void
edit_ptn_bounds(void)
{
char buf[40]; int start, size, inp, partn;
msg_table_add(MSG_mbrpart_start_special);
msg_prompt_add(MSG_start, NULL, buf, sizeof buf);
inp = atoi(buf);
/*
* -0, -1, -2, -3: start at end of part # given
* 0: start of disk.
*/
if ((inp == 0 && buf[0] == '-') || (inp < 0 && inp >= -3)) {
partn = -inp;
start = part[partn].mbrp_start + part[partn].mbrp_size;
} else if (inp == 0)
start = bsec;
else
start = NUMSEC(inp, sizemult, dlcylsize);
if (sizemult > 1 && start < bsec)
start = bsec;
msg_table_add(MSG_mbrpart_size_special);
msg_prompt_add(MSG_size, NULL, buf, 40);
inp = atoi(buf);
/*
* -0, -1, -2, -3: until start of part # given
* 0: end of disk
*/
if ((inp == 0 && buf[0] == '-') || (inp < 0 && inp >= -3)) {
partn = -inp;
size = part[partn].mbrp_start - start;
} else if (inp == 0)
size = dlsize - start;
else
size = NUMSEC(inp, sizemult, dlcylsize);
if (sizemult > 1 && start == bsec)
size -= bsec;
if (start + size > dlsize)
size = dlsize - start;
if (size < 0) {
size = 0;
start = 0;
}
part[editpart].mbrp_start = start;
part[editpart].mbrp_size = size;
}
int
partsoverlap(struct mbr_partition *part, int i, int j)
{
/*
* If the size or type of either partition is zero, they don't
* overlap by definition.
*/
if (part[i].mbrp_size == 0 || part[j].mbrp_size == 0 ||
part[i].mbrp_typ == 0 || part[j].mbrp_typ == 0)
return 0;
return
(part[i].mbrp_start < part[j].mbrp_start &&
part[i].mbrp_start + part[i].mbrp_size > part[j].mbrp_start)
||
(part[i].mbrp_start > part[j].mbrp_start &&
part[i].mbrp_start < part[j].mbrp_start + part[j].mbrp_size)
||
(part[i].mbrp_start == part[j].mbrp_start);
}
char *
get_partname(int i)
{
int j;
static char unknown[32];
for (j = 0; part_ids[j].id != -1; j++)
if (part_ids[j].id == part[i].mbrp_typ)
return part_ids[j].name;
snprintf(unknown, sizeof unknown, "Unknown (%d)", part[i].mbrp_typ);
return unknown;
}
void
disp_cur_part(struct mbr_partition *part, int sel, int disp)
{
int i, start, stop, rsize, rend;
if (disp < 0)
start = 0, stop = 4;
else
start = disp, stop = disp+1;
msg_table_add(MSG_part_header, dlsize/sizemult, multname, multname,
multname, multname);
for (i = start; i < stop; i++) {
if (sel == i)
msg_standout();
if (part[i].mbrp_typ == 0 ||
(part[i].mbrp_size == 0 && part[i].mbrp_start == 0))
msg_table_add(MSG_part_row_start_unused, i);
else {
rsize = part[i].mbrp_size / sizemult;
if (part[i].mbrp_size % sizemult)
rsize++;
rend = (part[i].mbrp_start + part[i].mbrp_size) / sizemult;
if ((part[i].mbrp_start + part[i].mbrp_size) % sizemult)
rend++;
msg_table_add(MSG_part_row_start_used, i,
part[i].mbrp_start / sizemult, rend, rsize);
}
msg_table_add(MSG_part_row_end, get_partname(i));
if (sel == i)
msg_standend();
}
}
int
read_mbr(const char *disk, mbr_sector_t *mbr)
{
char diskpath[MAXPATHLEN];
int fd, i;
struct mbr_partition *mbrp;
/* Open the disk. */
fd = opendisk(disk, O_RDONLY, diskpath, sizeof(diskpath), 0);
if (fd < 0)
goto bad_mbr;
if (pread(fd, mbr, sizeof *mbr, 0) < sizeof *mbr)
goto bad_mbr;
if (!valid_mbr(mbr))
goto bad_mbr;
mbrp = &mbr->mbr_parts[0];
for (i = 0; i < NMBRPART; i++) {
if (mbrp[i].mbrp_typ != 0) {
mbrp[i].mbrp_start =
le_to_native32(mbrp[i].mbrp_start);
mbrp[i].mbrp_size =
le_to_native32(mbrp[i].mbrp_size);
} else {
/* type is unused, discard scum */
mbrp[i].mbrp_start = 0;
mbrp[i].mbrp_size = 0;
}
}
(void)close(fd);
return 0;
bad_mbr:
if (fd >= 0)
close(fd);
memset(&mbr->mbr_parts, 0, sizeof mbr->mbr_parts);
mbr->mbr_signature = native_to_le16(MBR_MAGIC);
return -1;
}
int
write_mbr(const char *disk, mbr_sector_t *mbr, int convert)
{
char diskpath[MAXPATHLEN];
int fd, i, ret = 0;
struct mbr_partition *mbrp;
u_int32_t pstart, psize;
/* Open the disk. */
fd = opendisk(disk, O_WRONLY, diskpath, sizeof(diskpath), 0);
if (fd < 0)
return -1;
mbrp = &mbr->mbr_parts[0];
for (i = 0; i < NMBRPART; i++) {
if (mbrp[i].mbrp_start == 0 &&
mbrp[i].mbrp_size == 0) {
mbrp[i].mbrp_scyl = 0;
mbrp[i].mbrp_shd = 0;
mbrp[i].mbrp_ssect = 0;
mbrp[i].mbrp_ecyl = 0;
mbrp[i].mbrp_ehd = 0;
mbrp[i].mbrp_esect = 0;
} else {
pstart = mbrp[i].mbrp_start;
psize = mbrp[i].mbrp_size;
mbrp[i].mbrp_start = native_to_le32(pstart);
mbrp[i].mbrp_size = native_to_le32(psize);
if (convert) {
convert_mbr_chs(bcyl, bhead, bsec,
&mbrp[i].mbrp_scyl, &mbrp[i].mbrp_shd,
&mbrp[i].mbrp_ssect, pstart);
convert_mbr_chs(bcyl, bhead, bsec,
&mbrp[i].mbrp_ecyl, &mbrp[i].mbrp_ehd,
&mbrp[i].mbrp_esect, pstart + psize - 1);
}
}
}
if (pwrite(fd, mbr, sizeof *mbr, 0) < 0)
ret = -1;
(void)close(fd);
return ret;
}
int
valid_mbr(mbr_sector_t *mbr)
{
return (le_to_native16(mbr->mbr_signature) == MBR_MAGIC);
}
static void
convert_mbr_chs(int cyl, int head, int sec,
u_int8_t *cylp, u_int8_t *headp, u_int8_t *secp,
u_int32_t relsecs)
{
unsigned int tcyl, temp, thead, tsec;
temp = cyl * head * sec - 1;
if (relsecs >= temp)
relsecs = temp;
temp = head * sec;
tcyl = relsecs / temp;
relsecs %= temp;
thead = relsecs / sec;
tsec = (relsecs % sec) + 1;
*cylp = MBR_PUT_LSCYL(tcyl);
*headp = thead;
*secp = MBR_PUT_MSCYLANDSEC(tcyl, tsec);
}
/*
* This function is ONLY to be used as a last resort to provide a
* hint for the user. Ports should provide a more reliable way
* of getting the BIOS geometry. The i386 code, for example,
* uses the BIOS geometry as passed on from the bootblocks,
* and only uses this as a hint to the user when that information
* is not present, or a match could not be made with a NetBSD
* device.
*/
#define MAXCYL 1023 /* Possibly 1024 */
#define MAXHEAD 255 /* Possibly 256 */
#define MAXSECTOR 63
int
guess_biosgeom_from_mbr(mbr_sector_t *mbr, int *cyl, int *head, int *sec)
{
struct mbr_partition *parts = &mbr->mbr_parts[0];
int xcylinders, xheads, xsectors, i, j;
int c1, h1, s1, c2, h2, s2;
unsigned long a1, a2;
uint64_t num, denom;
/*
* The physical parameters may be invalid as bios geometry.
* If we cannot determine the actual bios geometry, we are
* better off picking a likely 'faked' geometry than leaving
* the invalid physical one.
*/
xcylinders = dlcyl;
xheads = dlhead;
xsectors = dlsec;
if (xcylinders > MAXCYL || xheads > MAXHEAD || xsectors > MAXSECTOR) {
xsectors = MAXSECTOR;
xheads = MAXHEAD;
xcylinders = disk->dd_totsec / (MAXSECTOR * MAXHEAD);
if (xcylinders > MAXCYL)
xcylinders = MAXCYL;
}
*cyl = xcylinders;
*head = xheads;
*sec = xsectors;
xheads = -1;
/* Try to deduce the number of heads from two different mappings. */
for (i = 0; i < NMBRPART * 2 - 1; i++) {
if (get_mapping(parts, i, &c1, &h1, &s1, &a1) < 0)
continue;
for (j = i + 1; j < NMBRPART * 2; j++) {
if (get_mapping(parts, j, &c2, &h2, &s2, &a2) < 0)
continue;
a1 -= s1;
a2 -= s2;
num = (uint64_t)h1 * a2 - (quad_t)h2 * a1;
denom = (uint64_t)c2 * a1 - (quad_t)c1 * a2;
if (denom != 0 && num % denom == 0) {
xheads = (int)(num / denom);
xsectors = a1 / (c1 * xheads + h1);
break;
}
}
if (xheads != -1)
break;
}
if (xheads == -1)
return -1;
/*
* Estimate the number of cylinders.
* XXX relies on get_disks having been called.
*/
xcylinders = disk->dd_totsec / xheads / xsectors;
/* Now verify consistency with each of the partition table entries.
* Be willing to shove cylinders up a little bit to make things work,
* but translation mismatches are fatal. */
for (i = 0; i < NMBRPART * 2; i++) {
if (get_mapping(parts, i, &c1, &h1, &s1, &a1) < 0)
continue;
if (xsectors * (c1 * xheads + h1) + s1 != a1)
return -1;
if (c1 >= xcylinders)
xcylinders = c1 + 1;
}
/*
* Everything checks out. Reset the geometry to use for further
* calculations.
*/
*cyl = MIN(xcylinders, MAXCYL);
*head = xheads;
*sec = xsectors;
return 0;
}
static int
get_mapping(mbr_partition_t *parts, int i,
int *cylinder, int *head, int *sector, unsigned long *absolute)
{
struct mbr_partition *apart = &parts[i / 2];
if (apart->mbrp_typ == 0)
return -1;
if (i % 2 == 0) {
*cylinder = MBR_PCYL(apart->mbrp_scyl, apart->mbrp_ssect);
*head = apart->mbrp_shd;
*sector = MBR_PSECT(apart->mbrp_ssect) - 1;
*absolute = le32toh(apart->mbrp_start);
} else {
*cylinder = MBR_PCYL(apart->mbrp_ecyl, apart->mbrp_esect);
*head = apart->mbrp_ehd;
*sector = MBR_PSECT(apart->mbrp_esect) - 1;
*absolute = le32toh(apart->mbrp_start)
+ le32toh(apart->mbrp_size) - 1;
}
/* Sanity check the data against max values */
if ((((*cylinder * MAXHEAD) + *head) * MAXSECTOR + *sector) < *absolute)
/* cannot be a CHS mapping */
return -1;
return 0;
}
#ifdef BOOTSEL
void
disp_bootsel(void)
{
int i;
msg_display(MSG_configbootsel);
msg_table_add(MSG_bootsel_header);
for (i = 0; i < NMBRPART; i++) {
msg_table_add(MSG_bootsel_row, i, get_partname(i),
mbs->mbrb_nametab[i]);
}
msg_display_add(MSG_newline);
msg_display_add(MSG_bootseltimeout, (10 * mbs->mbrb_timeo + 9) / 182);
msg_display_add(MSG_defbootselopt);
if (mbs->mbrb_defkey == SCAN_ENTER)
msg_display_add(MSG_defbootseloptactive);
else if (mbs->mbrb_defkey < (SCAN_1 + 10))
msg_display_add(MSG_defbootseloptpart, defbootselpart);
else
msg_display_add(MSG_defbootseloptdisk, defbootseldisk);
}
void
edit_bootsel_entry(int ptn)
{
if (part[ptn].mbrp_typ != 0)
msg_prompt(MSG_bootselitemname, mbs->mbrb_nametab[ptn],
mbs->mbrb_nametab[ptn], 8);
}
void
edit_bootsel_timeout(void)
{
char tstr[8];
unsigned timo;
do {
snprintf(tstr, 8, "%u", (10 * mbs->mbrb_timeo + 9) / 182);
msg_prompt(MSG_bootseltimeoutval, tstr, tstr, 8);
timo = (unsigned)atoi(tstr);
} while (timo > 3600);
mbs->mbrb_timeo = (u_int16_t)((timo * 182) / 10);
}
void
edit_bootsel_default_ptn(int ptn)
{
int i;
int key = SCAN_1;
if (mbs->mbrb_nametab[ptn][0] == 0 || part[ptn].mbrp_typ == 0)
return;
for (i = 0; i < ptn; i++)
if (mbs->mbrb_nametab[i][0] != 0 && part[i].mbrp_typ != 0)
key++;
mbs->mbrb_defkey = key;
defbootselpart = ptn;
}
void
edit_bootsel_default_disk(int disk)
{
mbs->mbrb_defkey = SCAN_F1 + disk;
defbootseldisk = disk;
}
void
configure_bootsel(void)
{
struct mbr_partition *parts = &mbr.mbr_parts[0];
int i;
const char *name, *cp;
mbs = &mbr.mbr_bootsel;
/*
* Setup default labels for partitions, since if not done by user
* they don't get set and bootselector doesn't 'appear' when
* it's loaded.
*/
for (i = 0; i < NMBRPART; i++) {
if (parts[i].mbrp_typ == 0 ||
parts[i].mbrp_typ == MBR_PTYPE_LNXSWAP ||
MBR_IS_EXTENDED(parts[i].mbrp_typ))
mbs->mbrb_nametab[i][0] = 0;
}
for (i = 0; i < NMBRPART; i++) {
if (parts[i].mbrp_typ == MBR_PTYPE_NETBSD &&
mbs->mbrb_nametab[i][0] != 0)
goto labels_ok;
}
for (i = 0; i < NMBRPART; i++) {
if (parts[i].mbrp_typ == 0 ||
parts[i].mbrp_typ == MBR_PTYPE_LNXSWAP ||
MBR_IS_EXTENDED(parts[i].mbrp_typ) ||
mbs->mbrb_nametab[i][0] != '\0')
continue;
/* Default to first word of partition name */
name = get_partname(i);
cp = strchr(name, ' ');
snprintf(mbs->mbrb_nametab[i], sizeof(mbs->mbrb_nametab[0]),
"%.*s", cp != NULL ? cp - name : 256, name);
}
labels_ok:
process_menu(MENU_configbootsel, NULL);
#if 0
/* The current bootselect code doesn't need this... */
mbs->mbrb_flags &= ~BFL_EXTINT13;
for (i = 0; i < NMBRPART; i++) {
if (parts[i].mbrp_typ != 0 &&
parts[i].mbrp_start >= (bcyl * bhead * bsec)) {
mbs->mbrb_flags |= BFL_EXTINT13;
break;
}
}
#endif
}
#endif