NetBSD/distrib/utils/sysinst/mbr.c
garbled 865c31ac7b This change includes the following:
Scripting and logging functionality for sysinst.
Child programs are run in a "display window" so you can actually see what
	they did before the screen flashes back and you loose it all.
Lots of curses fixups.  Removed nasty endwins that mangled the tty upon
	rentry.
Change the yes/no box to accept Y or N, and not require cursor motion to
	decide one or the other.
Perform curses redraws when doing things that could cause the kernel to
	spew printfs onto your screen.
1999-01-21 08:02:17 +00:00

346 lines
8.3 KiB
C

/* $NetBSD: mbr.c,v 1.9 1999/01/21 08:02:18 garbled 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");
snprintf(res, 80, "%d", bcyl);
msg_prompt_add(MSG_cylinders, res, res, 80);
bcyl = atoi(res);
snprintf(res, 80, "%d", bhead);
msg_prompt_add(MSG_heads, res, res, 80);
bhead = atoi(res);
snprintf(res, 80, "%d", bsec);
msg_prompt_add(MSG_sectors, res, res, 80);
bsec = atoi(res);
}
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) {
if (logging)
(void)fprintf(log, "User answered no to destroy other data, aborting.\n");
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();
}
}