NetBSD/distrib/utils/sysinst/mbr.c

341 lines
8.1 KiB
C

/* $NetBSD: mbr.c,v 1.7 1998/06/20 13:05:49 mrg Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
* All rights reserved.
* * 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 develooped 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.
*
*/
/* mbr.c -- DOS Master Boot Record editing code */
#include <stdio.h>
#include <util.h>
#include "defs.h"
#include "md.h"
#include "msg_defs.h"
#include "menu_defs.h"
struct part_id {
int id;
char *name;
} part_ids[] = {
{0, "unused"},
{1, "Primary DOS, 12 bit FAT"},
{4, "Primary DOS, 16 bit FAT <32M"},
{5, "Extended DOS"},
{6, "Primary DOS, 16-bit FAT >32MB"},
{7, "NTFS"},
{131, "Linux native"},
{131, "Linux swap"},
{165, "old NetBSD/FreeBSD/386BSD"},
{169, "NetBSD"},
{-1, "Unknown"},
};
/*
* Define symbolic name for MBR IDs if undefined, for backwards
* source compatibility.
*/
#ifndef DOSPTYP_NETBSD
#define DOSPTYP_NETBSD 0xa9
#endif
#ifndef DOSPTYP_386BSD
#define DOSPTYP_386BSD 0xa5
#endif
/*
* Which MBR partition ID to use for a newly-created NetBSD partition.
* Left patchable as we're in the middle of changing partition IDs.
*/
#ifdef notyet
#define DOSPTYP_OURS DOSPTYP_NETBSD /* NetBSD >= 1.3D */
#else
#define DOSPTYP_OURS DOSPTYP_386BSD /* 386bsd, FreeBSD, old NetBSD */
#endif
int dosptyp_nbsd = DOSPTYP_OURS;
/* prototypes */
int otherpart __P((int id));
int ourpart __P((int id));
int edit_mbr __P((void));
/*
* First, geometry stuff...
*/
int
check_geom()
{
return bcyl <= 1024 && bsec < 64 && bcyl > 0 && bhead > 0 && bsec > 0;
}
/*
* get C/H/S geometry from user via menu interface and
* store in globals.
*/
void
set_fdisk_geom()
{
char res[80];
msg_display_add(MSG_setbiosgeom);
disp_cur_geom();
msg_printf_add("\n");
msg_prompt_add(MSG_cylinders, NULL, res, 80);
bcyl = atoi(res);
msg_prompt_add(MSG_heads, NULL, res, 80);
bhead = atoi(res);
msg_prompt_add(MSG_sectors, NULL, res, 80);
bsec = atoi(res);
bstuffset = 1;
}
void
disp_cur_geom()
{
msg_display_add(MSG_realgeom, dlcyl, dlhead, dlsec);
msg_display_add(MSG_biosgeom, bcyl, bhead, bsec);
}
/*
* Then, the partition stuff...
*/
int
otherpart(id)
int id;
{
return (id != 0 && id != DOSPTYP_386BSD && id != DOSPTYP_NETBSD);
}
int
ourpart(id)
int id;
{
return (id != 0 && (id == DOSPTYP_386BSD || id == DOSPTYP_NETBSD));
}
/*
* Let user change incore Master Boot Record partitions via menu.
*/
int
edit_mbr()
{
int i, j;
/* Ask full/part */
msg_display(MSG_fullpart, diskdev);
process_menu(MENU_fullpart);
/* DOS fdisk label checking and value setting. */
if (usefull) {
int otherparts = 0;
int ourparts = 0;
int i;
/* Count nonempty, non-BSD partitions. */
for (i = 0; i < 4; i++) {
otherparts += otherpart(part[0][ID]);
/* check for dualboot *bsd too */
ourparts += ourpart(part[0][ID]);
}
/* Ask if we really want to blow away non-NetBSD stuff */
if (otherparts != 0 || ourparts > 1) {
msg_display(MSG_ovrwrite);
process_menu(MENU_noyes);
if (!yesno) {
endwin();
return 0;
}
}
/* Set the partition information for full disk usage. */
part[0][ID] = part[0][SIZE] = 0;
part[0][SET] = 1;
part[1][ID] = part[1][SIZE] = 0;
part[1][SET] = 1;
part[2][ID] = part[2][SIZE] = 0;
part[2][SET] = 1;
part[3][ID] = dosptyp_nbsd;
part[3][SIZE] = bsize - bsec;
part[3][START] = bsec;
part[3][FLAG] = 0x80;
part[3][SET] = 1;
ptstart = bsec;
ptsize = bsize - bsec;
fsdsize = dlsize;
fsptsize = dlsize - bsec;
fsdmb = fsdsize / MEG;
activepart = 3;
} else {
int numbsd, overlap;
int numfreebsd, freebsdpart; /* dual-boot */
/* Ask for sizes, which partitions, ... */
ask_sizemult();
bsdpart = freebsdpart = -1;
activepart = -1;
for (i = 0; i<4; i++)
if (part[i][FLAG] != 0)
activepart = i;
do {
process_menu (MENU_editparttable);
numbsd = 0;
bsdpart = -1;
freebsdpart = -1;
numfreebsd = 0;
overlap = 0;
yesno = 0;
for (i=0; i<4; i++) {
/* Count 386bsd/FreeBSD/NetBSD(old) partitions */
if (part[i][ID] == DOSPTYP_386BSD) {
freebsdpart = i;
numfreebsd++;
}
/* Count NetBSD-only partitions */
if (part[i][ID] == DOSPTYP_NETBSD) {
bsdpart = i;
numbsd++;
}
for (j = i+1; j<4; j++)
if (partsoverlap(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);
}
} while (yesno && (numbsd != 1 || overlap));
if (numbsd == 0) {
msg_display(MSG_nobsdpart);
process_menu(MENU_ok);
return 0;
}
if (numbsd > 1) {
msg_display(MSG_multbsdpart, bsdpart);
process_menu(MENU_ok);
}
ptstart = part[bsdpart][START];
ptsize = part[bsdpart][SIZE];
fsdsize = dlsize;
if (ptstart + ptsize < bsize)
fsptsize = ptsize;
else
fsptsize = dlsize - ptstart;
fsdmb = fsdsize / MEG;
/* Ask if a boot selector is wanted. XXXX */
}
/* Compute minimum NetBSD partition sizes (in sectors). */
minfsdmb = (80 + 4*rammb) * (MEG / sectorsize);
if (usefull)
swapadj = bsec;
return 1;
}
int
partsoverlap(i, j)
int i;
int j;
{
if (part[i][SIZE] == 0 || part[j][SIZE] == 0)
return 0;
return
(part[i][START] < part[j][START] &&
part[i][START] + part[i][SIZE] > part[j][START])
||
(part[i][START] > part[j][START] &&
part[i][START] < part[j][START] + part[j][SIZE])
||
(part[i][START] == part[j][START]);
}
void
disp_cur_part(sel, disp)
int sel;
int disp;
{
int i, j, start, stop, rsize, rend;
if (disp < 0)
start = 0, stop = 4;
else
start = disp, stop = disp+1;
msg_display_add(MSG_part_head, multname, multname, multname);
for (i = start; i < stop; i++) {
if (sel == i)
msg_standout();
if (part[i][SIZE] == 0 && part[i][START] == 0)
msg_printf_add("%d %36s ", i, "");
else {
rsize = part[i][SIZE] / sizemult;
if (part[i][SIZE] % sizemult)
rsize++;
rend = (part[i][START] + part[i][SIZE]) / sizemult;
if ((part[i][SIZE] + part[i][SIZE]) % sizemult)
rend++;
msg_printf_add("%d %12d%12d%12d ", i,
part[i][START] / sizemult, rsize, rend);
}
for (j = 0; part_ids[j].id != -1 &&
part_ids[j].id != part[i][ID]; j++);
msg_printf_add ("%s\n", part_ids[j].name);
if (sel == i) msg_standend();
}
}