From b4740339e8ea3ab0cf35ae4ed79f91bfc829b56d Mon Sep 17 00:00:00 2001 From: Paul Richards Date: Fri, 21 Oct 1994 18:08:33 +0000 Subject: [PATCH] Fix all the bugs introduced by the source shuffle. All the mbr code now seems to be working. We can build a basic unix disklabel in any existing DOS partition while retaining the existing mbr bootcode or we can install to the whole disk which puts FreeBSD's boot code into the MBR and creates a clean MBR partition table with FreeBSD in partition 0 taking up the whole disk. --- sbin/sysinstall/Makefile | 2 +- sbin/sysinstall/bootarea.c | 26 +++++--- sbin/sysinstall/bootarea.h | 4 +- sbin/sysinstall/mbr.c | 123 +++++++++++++++++++++++------------ sbin/sysinstall/mbr.h | 4 +- sbin/sysinstall/stage1.c | 84 +++++++++++++----------- sbin/sysinstall/sysinstall.h | 20 +----- sbin/sysinstall/utils.c | 52 ++++++++++++--- 8 files changed, 195 insertions(+), 120 deletions(-) diff --git a/sbin/sysinstall/Makefile b/sbin/sysinstall/Makefile index 2dd748531ce7..addeab79a621 100644 --- a/sbin/sysinstall/Makefile +++ b/sbin/sysinstall/Makefile @@ -8,7 +8,7 @@ SRCS = stage1.c dkcksum.c bootarea.c mbr.c \ utils.c termcap.c exec.c \ stage0.c stage2.c stage3.c main.c -CFLAGS += -Wall +CFLAGS += -Wall -g LDADD = -ldialog -lncurses -lmytinfo DPADD = ${LIBDIALOG} ${LIBNCURSES} ${LIBMYTINFO} diff --git a/sbin/sysinstall/bootarea.c b/sbin/sysinstall/bootarea.c index a1fba2b18e8b..0e0cbb85305e 100644 --- a/sbin/sysinstall/bootarea.c +++ b/sbin/sysinstall/bootarea.c @@ -23,16 +23,16 @@ #include #include #include +#include #include "mbr.h" #include "bootarea.h" #include "sysinstall.h" -char boot1[] = BOOT1; -char boot2[] = BOOT2; - extern char *bootblocks; extern struct mbr *mbr; +extern char boot1[]; +extern char boot2[]; int enable_label(int fd) @@ -88,15 +88,17 @@ build_bootblocks(struct disklabel *label) int fd; + sprintf(scratch, "\nLoading boot code from %s\n", boot1); + dialog_msgbox(TITLE, scratch, 5, 60, 0); fd = open(boot1, O_RDONLY); if (fd < 0) { sprintf(errmsg, "Couldn't open boot file %s\n", boot1); return(-1); } - if (read(fd, bootblocks, (int)label->d_secsize) < 0) { + if (read(fd, bootblocks, MBRSIZE) < 0) { sprintf(errmsg, "Couldn't read from boot file %s\n", boot1); - return(-1); + return(-1); } if (close(fd) == -1) { @@ -104,14 +106,18 @@ build_bootblocks(struct disklabel *label) return(-1); } + dialog_clear(); + sprintf(scratch, "\nLoading boot code from %s\n", boot1); + dialog_msgbox(TITLE, scratch, 5, 60, 0); + fd = open(boot2, O_RDONLY); if (fd < 0) { sprintf(errmsg, "Couldn't open boot file %s\n", boot2); return(-1); } - if (read(fd, &bootblocks[label->d_secsize], - (int)(label->d_bbsize - label->d_secsize)) < 0) { + if (read(fd, &bootblocks[MBRSIZE], + (int)(label->d_bbsize - MBRSIZE)) < 0) { sprintf(errmsg, "Couldn't read from boot file %s\n", boot2); return(-1); } @@ -121,10 +127,12 @@ build_bootblocks(struct disklabel *label) return(-1); } - /* Write mbr partition table into bootblocks */ + /* Copy DOS partition area into bootblocks */ bcopy(mbr->dospart, &bootblocks[DOSPARTOFF], - sizeof(struct dos_partition) * NDOSPART); + sizeof(struct dos_partition) * 4); + + dialog_clear(); /* Write the disklabel into the bootblocks */ diff --git a/sbin/sysinstall/bootarea.h b/sbin/sysinstall/bootarea.h index bbb8e1bdcb8f..96413f6d7004 100644 --- a/sbin/sysinstall/bootarea.h +++ b/sbin/sysinstall/bootarea.h @@ -12,8 +12,8 @@ * its use. */ -#define BOOT1 "/usr/mdec/sdboot" -#define BOOT2 "/usr/mdec/bootsd" +#define BOOT1 "/stand/sdboot" +#define BOOT2 "/stand/bootsd" /* XXX -- calculate these, this is nasty */ #define DEFFSIZE 1024 diff --git a/sbin/sysinstall/mbr.c b/sbin/sysinstall/mbr.c index c0e73813daa0..912bb8746d29 100644 --- a/sbin/sysinstall/mbr.c +++ b/sbin/sysinstall/mbr.c @@ -13,17 +13,20 @@ */ #include +#include +#include +#include + #include #include #include -#include -#include #include "mbr.h" +#include "sysinstall.h" extern struct mbr *mbr; -extern char *errmsg; extern int inst_part; +extern int whole_disk; struct part_type part_types[] = PARTITION_TYPES @@ -50,7 +53,7 @@ read_mbr(int fd, struct mbr *mbr) sprintf(errmsg, "Couldn't seek for master boot record read\n"); return(-1); } - if (read(fd, &(mbr->bootcode), 512) == -1) { + if (read(fd, &(mbr->bootcode), MBRSIZE) == -1) { sprintf(errmsg, "Failed to read master boot record\n"); return(-1); } @@ -70,11 +73,17 @@ write_mbr(int fd, struct mbr *mbr) return(-1); } + if (enable_label(fd) == -1) + return(-1); + if (write(fd, mbr->bootcode, MBRSIZE) == -1) { sprintf(errmsg, "Failed to write master boot record\n"); return(-1); } + if(disable_label(fd) == -1) + return(-1); + return(0); } @@ -97,20 +106,20 @@ show_mbr(struct mbr *mbr) y = (i * 11) + 2; mvwprintw(window, y, x, "Partition %d: flags = %x", (i*2)+j, mbr->dospart[(i*2)+j].dp_flag); - mvwprintw(window, y+1, x, "Starting at (H%d, S%d, C%d)", + mvwprintw(window, y+1, x, "Starting at (C%d, H%d, S%d)", + mbr->dospart[(i*2)+j].dp_scyl, mbr->dospart[(i*2)+j].dp_shd, - mbr->dospart[(i*2)+j].dp_ssect, - mbr->dospart[(i*2)+j].dp_scyl); + mbr->dospart[(i*2)+j].dp_ssect); mvwprintw(window, y+2, x, "Type: %s (%x)", part_type(mbr->dospart[(i*2)+j].dp_typ), mbr->dospart[(i*2)+j].dp_typ); - mvwprintw(window, y+3, x, "Ending at (H%d, S%d, C%d)", - mbr->dospart[(i*2)+j].dp_shd, - mbr->dospart[(i*2)+j].dp_esect, - mbr->dospart[(i*2)+j].dp_ecyl); + mvwprintw(window, y+3, x, "Ending at (C%d, H%d, S%d)", + mbr->dospart[(i*2)+j].dp_ecyl, + mbr->dospart[(i*2)+j].dp_ehd, + mbr->dospart[(i*2)+j].dp_esect); mvwprintw(window, y+4, x, "Absolute start sector %ld", mbr->dospart[(i*2)+j].dp_start); - mvwprintw(window, y+5, x, "Size %ld", mbr->dospart[(i*2)+j].dp_size); + mvwprintw(window, y+5, x, "Size (in sectors) %ld", mbr->dospart[(i*2)+j].dp_size); } } refresh(); @@ -119,14 +128,40 @@ show_mbr(struct mbr *mbr) key = wgetch(window); delwin(window); + dialog_clear(); } -void -clear_mbr(struct mbr *mbr) +int +clear_mbr(struct mbr *mbr, char *bootcode) { int i; + int fd; + + /* + * If installing to the whole disk + * then clobber any existing bootcode. + */ + + sprintf(scratch, "\nLoading MBR code from %s\n", bootcode); + dialog_msgbox(TITLE, scratch, 5, 60, 0); + fd = open(bootcode, O_RDONLY); + if (fd < 0) { + sprintf(errmsg, "Couldn't open boot file %s\n", bootcode); + return(-1); + } + + if (read(fd, mbr->bootcode, MBRSIZE) < 0) { + sprintf(errmsg, "Couldn't read from boot file %s\n", bootcode); + return(-1); + } + + if (close(fd) == -1) { + sprintf(errmsg, "Couldn't close boot file %s\n", bootcode); + return(-1); + } /* Create an empty partition table */ + for (i=0; i < NDOSPART; i++) { mbr->dospart[i].dp_flag = 0; mbr->dospart[i].dp_shd = 0; @@ -139,47 +174,49 @@ clear_mbr(struct mbr *mbr) mbr->dospart[i].dp_start = 0; mbr->dospart[i].dp_size = 0; } + + mbr->magic = MBR_MAGIC; + + dialog_clear(); + return(0); } int -build_mbr(struct mbr *mbr, struct disklabel *label) +build_mbr(struct mbr *mbr, char *bootcode, struct disklabel *lb) { int i; + struct dos_partition *dp = &mbr->dospart[inst_part]; - /* - * This is the biggie, need to spend some time getting all - * the different possibilities sorted out. - */ - - if (inst_part == -1) { + if (whole_disk) { /* Install to entire disk */ - clear_mbr(mbr); - mbr->dospart[0].dp_flag = ACTIVE; - mbr->dospart[0].dp_shd = 1; - mbr->dospart[0].dp_ssect = 0; - mbr->dospart[0].dp_scyl = 0; - mbr->dospart[0].dp_typ = DOSPTYP_386BSD ; - mbr->dospart[0].dp_ehd = label->d_ntracks; - mbr->dospart[0].dp_esect = label->d_nsectors; - mbr->dospart[0].dp_ecyl = label->d_ncylinders; - mbr->dospart[0].dp_start = 0; - mbr->dospart[0].dp_size = - label->d_ntracks * label->d_nsectors * label->d_ncylinders; - return(1); - } else { - /* Validate partition - XXX need to spend some time making this robust */ - if ((inst_part) && (!mbr->dospart[inst_part].dp_start)) { - strcpy(errmsg, "The start address of the selected partition is 0\n"); - return(0); - } + if (clear_mbr(mbr, bootcode) == -1) + return(-1); + dp->dp_scyl = 0; + dp->dp_shd = 1; + dp->dp_ssect = 1; + dp->dp_ecyl = lb->d_ncylinders - 1; + dp->dp_ehd = lb->d_ntracks - 1; + dp->dp_esect = lb->d_nsectors; + dp->dp_start = (dp->dp_scyl * lb->d_ntracks * lb->d_nsectors) + + (dp->dp_shd * lb->d_nsectors) + + dp->dp_ssect - 1; + dp->dp_size = (lb->d_nsectors * lb->d_ntracks * lb->d_ncylinders) - dp->dp_start; + } + + /* Validate partition - XXX need to spend some time making this robust */ + if (!dp->dp_start) { + strcpy(errmsg, "The start address of the selected partition is 0\n"); + return(-1); } /* Set partition type to FreeBSD and make it the only active partition */ + for (i=0; i < NDOSPART; i++) mbr->dospart[i].dp_flag &= ~ACTIVE; - mbr->dospart[inst_part].dp_typ = DOSPTYP_386BSD; - mbr->dospart[inst_part].dp_flag = ACTIVE; - return(1); + dp->dp_typ = DOSPTYP_386BSD; + dp->dp_flag = ACTIVE; + + return(0); } void diff --git a/sbin/sysinstall/mbr.h b/sbin/sysinstall/mbr.h index 45abad3d901d..ea4de0245553 100644 --- a/sbin/sysinstall/mbr.h +++ b/sbin/sysinstall/mbr.h @@ -78,6 +78,6 @@ extern int disable_label(int); extern int write_mbr(int, struct mbr *); extern int read_mbr(int, struct mbr *); extern void show_mbr(struct mbr *); -extern void clear_mbr(struct mbr *); +extern int clear_mbr(struct mbr *, char *); extern void edit_mbr(struct mbr *, struct disklabel *); -extern int build_mbr(struct mbr *, struct disklabel *); +extern int build_mbr(struct mbr *, char *, struct disklabel *); diff --git a/sbin/sysinstall/stage1.c b/sbin/sysinstall/stage1.c index 035ed86ece6a..9c2a160fbaaa 100644 --- a/sbin/sysinstall/stage1.c +++ b/sbin/sysinstall/stage1.c @@ -26,10 +26,7 @@ #include #include #include -#include -#include #include -#include #include #include @@ -49,7 +46,8 @@ struct mbr *mbr; int no_disks = 0; int inst_disk = 0; int inst_part = 0; -int custom_install; +int whole_disk = 0; +int custom_install = 0; int dialog_active = 0; void exit_sysinstall(); @@ -57,8 +55,9 @@ void exit_prompt(); extern char *part_type(int); extern int disk_size(int); -/* To make the binary as small as possible these should be malloc'd */ char selection[30]; +char boot1[] = BOOT1; +char boot2[] = BOOT2; int alloc_memory() @@ -184,7 +183,8 @@ select_disk() } if (dialog_menu("FreeBSD Installation", scratch, 10, 75, 5, no_disks, options, selection)) { - sprintf(scratch,"You did not select a valid disk"); + dialog_clear(); + sprintf(scratch,"\n\n\nYou did not select a valid disk.\n\n"); AskAbort(scratch); valid = 0; } @@ -216,18 +216,24 @@ select_partition(int disk) if (dialog_menu(TITLE, scratch, 10, 75, 5, 5, options, selection)) { sprintf(scratch,"You did not select a valid partition"); + dialog_clear(); AskAbort(scratch); valid = 0; } dialog_clear(); - choice = atoi(selection); - if (!choice) - if (dialog_yesno(TITLE, "Installing to the whole disk will erase all its present data.\n\nAre you sure you want to do this?", 10, 75)) + choice = atoi(selection) - 1; + if (choice == -1) { + whole_disk = 1; + choice = 0; + if (dialog_yesno(TITLE, "\n\nInstalling to the whole disk will erase all its current data.\n\nAre you sure you want to do this?", 10, 75)) { valid = 0; + whole_disk = 0; + } + } dialog_clear(); } while (!valid); - return(atoi(selection) - 1); + return(choice); } void @@ -237,31 +243,31 @@ stage1() int ok = 0; int ready = 0; + query_disks(); + while (!ready) { ready = 1; - query_disks(); inst_disk = select_disk(); -#ifdef DEBUG - read_mbr(avail_fds[inst_disk], mbr); - show_mbr(mbr); -#endif - if (read_mbr(avail_fds[inst_disk], mbr) == -1) { - sprintf(scratch, "The following error occured will trying to read the master boot record:\n\n%s\n\nIn order to install FreeBSD a new master boot record will have to be written which will mean all current data on the hard disk will be lost.", errmsg); + sprintf(scratch, "The following error occured will trying\nto read the master boot record:\n\n%s\nIn order to install FreeBSD a new master boot record\nwill have to be written which will mean all current\ndata on the hard disk will be lost.", errmsg); ok = 0; while (!ok) { AskAbort(scratch); if (!dialog_yesno(TITLE, "Are you sure you wish to proceed?", 10, 75)) { dialog_clear(); - clear_mbr(mbr); + if (clear_mbr(mbr, boot1) == -1) { + sprintf(scratch, "\n\nCouldn't create new master boot record.\n\n%s", errmsg); + Fatal(scratch);; + } ok = 1; } + dialog_clear(); } } - + if (custom_install) if (!dialog_yesno(TITLE, "Do you wish to edit the DOS partition table?", 10, 75)) { @@ -269,33 +275,42 @@ stage1() edit_mbr(mbr, &avail_disklabels[inst_disk]); } + dialog_clear(); inst_part = select_partition(inst_disk); ok = 0; while (!ok) { - if (build_mbr(mbr, &avail_disklabels[inst_disk])) + if (build_mbr(mbr, boot1, &avail_disklabels[inst_disk]) != -1) { + ready = 1; ok = 1; - else { - sprintf(scratch, "The DOS partition table is inconsistent.\n\n%s\n\nDo you wish to edit it by hand?", errmsg); + } else { + sprintf(scratch, "The DOS partition table is inconsistent.\n\n%s\nDo you wish to edit it by hand?", errmsg); if (!dialog_yesno(TITLE, scratch, 10, 75)) { - edit_mbr(mbr, &avail_disklabels[inst_disk]); dialog_clear(); + edit_mbr(mbr, &avail_disklabels[inst_disk]); } else { - AskAbort(""); + dialog_clear(); + AskAbort("Installation cannot proceed without\na valid master boot record\n"); ok = 1; ready = 0; } } + dialog_clear(); } - default_disklabel(&avail_disklabels[inst_disk], + if (ready) { + default_disklabel(&avail_disklabels[inst_disk], mbr->dospart[inst_part].dp_size, mbr->dospart[inst_part].dp_start); - build_bootblocks(&avail_disklabels[inst_disk]); + if (build_bootblocks(&avail_disklabels[inst_disk]) == -1) + Fatal(errmsg); + } + /* ready could have been reset above */ if (ready) { if (dialog_yesno(TITLE, "We are now ready to format the hard disk for FreeBSD.\n\nSome or all of the disk will be overwritten during this process.\n\nAre you sure you wish to proceed ?", 10, 75)) { - AskAbort(""); + dialog_clear(); + AskAbort("Do you want to quit?"); ready = 0; } dialog_clear(); @@ -303,15 +318,12 @@ stage1() } /* Write master boot record and bootblocks */ - write_mbr(avail_fds[inst_disk], mbr); - write_bootblocks(avail_fds[inst_disk], + if (write_mbr(avail_fds[inst_disk], mbr) == -1) + Fatal(errmsg); + if (write_bootblocks(avail_fds[inst_disk], mbr->dospart[inst_part].dp_start, - avail_disklabels[inst_disk].d_bbsize); - -#ifdef DEBUG - read_mbr(avail_fds[inst_disk], mbr); - show_mbr(mbr); -#endif + avail_disklabels[inst_disk].d_bbsize) == -1) + Fatal(errmsg); /* close all the open disks */ for (i=0; i < no_disks; i++) @@ -320,6 +332,4 @@ stage1() strerror(errno)); Fatal(errmsg); } - } - diff --git a/sbin/sysinstall/sysinstall.h b/sbin/sysinstall/sysinstall.h index b92bffd1fa69..a1efd3fe612b 100644 --- a/sbin/sysinstall/sysinstall.h +++ b/sbin/sysinstall/sysinstall.h @@ -29,22 +29,6 @@ #define COPYRIGHT_FILE "/COPYRIGHT" #define README_FILE "/README" -#define STATUSFILE "sysinstall.stat" -#define NOT_INSTALLED 0 -#define DISK_READY 1 -#define INSTALLED_BASE 2 - -struct sysinstall -{ - char media[90]; - int status; - char seq_name[64]; - int seq_size; - int seq_no; - char archive[64]; - char root_dev[90]; -}; - #ifndef EXTERN # define EXTERN extern #endif @@ -62,12 +46,14 @@ extern struct disklabel *avail_disklabels; extern u_short dkcksum(struct disklabel *); /* utils.c */ +void Abort __P((void)); +void ExitSysinstall __P((void)); void TellEm __P((char *fmt, ...)); void stage0 __P((void)); void *Malloc __P((size_t size)); char *StrAlloc __P((char *str)); void Fatal __P((char *fmt, ...)); -int AskAbort __P((char *fmt, ...)); +void AskAbort __P((char *fmt, ...)); void MountUfs __P((char *device, char *prefix, char *mountpoint, int do_mkdir)); void Mkdir __P((char *path)); diff --git a/sbin/sysinstall/utils.c b/sbin/sysinstall/utils.c index 5a4e9e5e2346..7f4900123adc 100644 --- a/sbin/sysinstall/utils.c +++ b/sbin/sysinstall/utils.c @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $Id: utils.c,v 1.5 1994/10/21 02:14:54 phk Exp $ + * $Id: utils.c,v 1.6 1994/10/21 04:43:07 ache Exp $ * */ @@ -23,6 +23,7 @@ #include #include #include +#include #include "sysinstall.h" @@ -36,6 +37,7 @@ TellEm(char *fmt, ...) vsnprintf(p, 2048, fmt, ap); va_end(ap); dialog_msgbox("Progress", p, 3, 75, 0); + dialog_clear(); free(p); } @@ -43,36 +45,68 @@ void Fatal(char *fmt, ...) { char *p; - int i = errno; va_list ap; p = Malloc(2048); va_start(ap,fmt); vsnprintf(p, 2048, fmt, ap); va_end(ap); - sprintf(p+strlen(p),"\nErrno= %d, %s.",i,strerror(i)); if (dialog_active) { dialog_msgbox("Fatal", p, 12, 75, 1); end_dialog(); } else fprintf(stderr, "Fatal -- %s", p); free(p); - exit(7); + ExitSysinstall(); } -int +void AskAbort(char *fmt, ...) { char *p; va_list ap; - int i; p = Malloc(2048); va_start(ap,fmt); vsnprintf(p, 2048, fmt, ap); va_end(ap); - i = dialog_yesno("Abort", p, 12, 75); + strcat(p, "\n\nDo you wish to abort the installation?"); + if (!dialog_yesno("Abort", p, 15, 60)) { + dialog_clear(); + Abort(); + } + dialog_clear(); free(p); - return i; +} + +void +Abort() +{ + if (dialog_yesno("Exit sysinstall","\n\nAre you sure you want to quit?", + 10, 40)) { + dialog_clear(); + return; + } + ExitSysinstall(); +} + +void +ExitSysinstall() +{ + if (getpid() == 1) { + clear(); + if (reboot(RB_AUTOBOOT) == -1) + if (dialog_active) { + dialog_clear(); + dialog_msgbox(TITLE, "\n\nCan't reboot machine -- hit reset button", + 5,30,0); + } else + fprintf(stderr, "Can't reboot the machine -- hit the reset button"); + while(1); + } else + clear(); + refresh(); + end_dialog(); + exit(0); } void * @@ -121,7 +155,7 @@ MountUfs(char *device, char *prefix, char *mountpoint, int do_mkdir) TellEm("mount /dev/%s /mnt%s",dbuf,pbuf); ufsargs.fspec = dbuf; if (mount(MOUNT_UFS,pbuf, 0, (caddr_t) &ufsargs) == -1) { - Fatal("Error mounting %s on : %s\n", + Fatal("Error mounting %s on %s : %s\n", dbuf, pbuf, strerror(errno)); } }