1995-05-01 21:56:32 +00:00
/*
* The new sysinstall program .
*
* This is probably the last program in the ` sysinstall ' line - the next
* generation being essentially a complete rewrite .
*
1995-05-11 06:47:46 +00:00
* $ Id : devices . c , v 1.13 1995 / 05 / 11 06 : 10 : 45 jkh Exp $
1995-05-01 21:56:32 +00:00
*
* Copyright ( c ) 1995
* Jordan Hubbard . All rights reserved .
*
* 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 ,
* verbatim and that no modifications are made prior to this
* point in the file .
* 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 by Jordan Hubbard
* for the FreeBSD Project .
* 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
* endorse or promote products derived from this software without specific
* prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ` ` 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 JORDAN HUBBARD OR HIS PETS 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 , LIFE 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 .
*
*/
# include "sysinstall.h"
1995-05-11 06:47:46 +00:00
# include <sys/fcntl.h>
1995-05-04 19:48:19 +00:00
# include <ctype.h>
1995-05-01 21:56:32 +00:00
1995-05-04 03:51:22 +00:00
/* Where we start displaying chunk information on the screen */
# define CHUNK_START_ROW 5
1995-05-08 21:39:40 +00:00
static char * cdrom_table [ ] = {
" cd0a " , " cd1a " , /* SCSI */
" mcd0a " , " mcd1a " , /* Mitsumi (old model) */
" scd0a " , " scd1a " , /* Sony CDROM */
" matcd0a " , " matcd1a " , /* Matsushita (SB) */
NULL ,
} ;
1995-05-01 21:56:32 +00:00
/* Get all device information for a given device class */
1995-05-08 10:20:56 +00:00
static Device *
1995-05-01 21:56:32 +00:00
device_get_all ( DeviceType which , int * ndevs )
{
char * * names ;
Device * devs = NULL ;
* ndevs = 0 ;
if ( which = = DEVICE_TYPE_DISK | | which = = DEVICE_TYPE_ANY ) {
if ( ( names = Disk_Names ( ) ) ! = NULL ) {
int i ;
for ( i = 0 ; names [ i ] ; i + + )
+ + * ndevs ;
devs = safe_malloc ( sizeof ( Device ) * ( * ndevs + 1 ) ) ;
for ( i = 0 ; names [ i ] ; i + + ) {
strcpy ( devs [ i ] . name , names [ i ] ) ;
devs [ i ] . type = DEVICE_TYPE_DISK ;
}
free ( names ) ;
}
}
1995-05-08 21:39:40 +00:00
if ( which = = DEVICE_TYPE_CDROM | | which = = DEVICE_TYPE_ANY ) {
char try [ FILENAME_MAX ] ;
int i , fd ;
for ( i = 0 ; cdrom_table [ i ] ; i + + ) {
snprintf ( try , FILENAME_MAX , " /mnt/dev/%s " , cdrom_table [ i ] ) ;
1995-05-11 06:47:46 +00:00
fd = open ( try , O_RDWR ) ;
1995-05-08 21:39:40 +00:00
if ( fd > 0 ) {
close ( fd ) ;
devs = safe_realloc ( devs , sizeof ( Device ) * ( * ndevs + 2 ) ) ;
strcpy ( devs [ * ndevs ] . name , cdrom_table [ i ] ) ;
devs [ ( * ndevs ) + + ] . type = DEVICE_TYPE_CDROM ;
break ;
}
}
}
/* Terminate the devices array */
devs [ * ndevs ] . name [ 0 ] = ' \0 ' ;
1995-05-01 21:56:32 +00:00
return devs ;
}
1995-05-04 03:51:22 +00:00
static struct chunk * chunk_info [ 10 ] ;
static int current_chunk ;
static void
1995-05-04 23:36:23 +00:00
record_chunks ( struct disk * d )
1995-05-01 21:56:32 +00:00
{
1995-05-04 03:51:22 +00:00
struct chunk * c1 ;
int i = 0 ;
int last_free = 0 ;
if ( ! d - > chunks )
1995-05-04 23:36:23 +00:00
msgFatal ( " No chunk list found for %s! " , d - > name ) ;
1995-05-04 03:51:22 +00:00
c1 = d - > chunks - > part ;
1995-05-07 05:58:57 +00:00
current_chunk = 0 ;
1995-05-04 03:51:22 +00:00
while ( c1 ) {
if ( c1 - > type = = unused & & c1 - > size > last_free ) {
last_free = c1 - > size ;
current_chunk = i ;
}
chunk_info [ i + + ] = c1 ;
c1 = c1 - > next ;
}
chunk_info [ i ] = NULL ;
1995-05-01 21:56:32 +00:00
}
1995-05-04 03:51:22 +00:00
static void
1995-05-04 23:36:23 +00:00
print_chunks ( struct disk * d )
1995-05-04 03:51:22 +00:00
{
int row ;
int i ;
attrset ( A_NORMAL ) ;
mvaddstr ( 0 , 0 , " Disk name: \t " ) ;
1995-05-07 03:38:03 +00:00
attrset ( A_REVERSE ) ; addstr ( d - > name ) ; attrset ( A_NORMAL ) ;
1995-05-04 23:36:23 +00:00
attrset ( A_REVERSE ) ; mvaddstr ( 0 , 55 , " Master Partition Editor " ) ; attrset ( A_NORMAL ) ;
1995-05-04 03:51:22 +00:00
mvprintw ( 1 , 0 ,
" BIOS Geometry: \t %lu cyls/%lu heads/%lu sectors " ,
d - > bios_cyl , d - > bios_hd , d - > bios_sect ) ;
mvprintw ( 3 , 1 , " %10s %10s %10s %8s %8s %8s %8s %8s " ,
" Offset " , " Size " , " End " , " Name " , " PType " , " Desc " ,
" Subtype " , " Flags " ) ;
for ( i = 0 , row = CHUNK_START_ROW ; chunk_info [ i ] ; i + + , row + + ) {
if ( i = = current_chunk )
1995-05-07 03:38:03 +00:00
attrset ( A_REVERSE ) ;
1995-05-04 03:51:22 +00:00
mvprintw ( row , 2 , " %10lu %10lu %10lu %8s %8d %8s %8d %6lx " ,
chunk_info [ i ] - > offset , chunk_info [ i ] - > size ,
chunk_info [ i ] - > end , chunk_info [ i ] - > name ,
chunk_info [ i ] - > type , chunk_n [ chunk_info [ i ] - > type ] ,
chunk_info [ i ] - > subtype , chunk_info [ i ] - > flags ) ;
if ( i = = current_chunk )
attrset ( A_NORMAL ) ;
}
}
static void
print_command_summary ( )
{
1995-05-04 23:36:23 +00:00
mvprintw ( 14 , 0 , " The following commands are supported (in upper or lower case): " ) ;
1995-05-06 09:34:24 +00:00
mvprintw ( 16 , 0 , " A = Use Entire Disk B = Bad Block Scan C = Create Partition " ) ;
mvprintw ( 17 , 0 , " D = Delete Partition G = Set BIOS Geometry S = Set Bootable " ) ;
mvprintw ( 18 , 0 , " U = Undo All Changes W = `Wizard' Mode ESC = Proceed to next screen " ) ;
mvprintw ( 20 , 0 , " The currently selected partition is displayed in " ) ;
1995-05-11 06:10:56 +00:00
attrset ( A_REVERSE ) ; addstr ( " reverse video. " ) ; attrset ( A_NORMAL ) ;
mvprintw ( 21 , 0 , " Use F1 or ? to get more help, arrow keys to move. " ) ;
1995-05-04 03:51:22 +00:00
move ( 0 , 0 ) ;
}
struct disk *
1995-05-04 23:36:23 +00:00
device_slice_disk ( struct disk * d )
1995-05-01 21:56:32 +00:00
{
char * p ;
1995-05-04 03:51:22 +00:00
int key = 0 ;
Boolean chunking ;
char * msg = NULL ;
1995-05-04 23:36:23 +00:00
char name [ 40 ] ;
1995-05-04 03:51:22 +00:00
1995-05-01 21:56:32 +00:00
dialog_clear ( ) ;
1995-05-04 03:51:22 +00:00
chunking = TRUE ;
1995-05-04 23:36:23 +00:00
strncpy ( name , d - > name , 40 ) ;
1995-05-04 03:51:22 +00:00
keypad ( stdscr , TRUE ) ;
1995-05-04 23:36:23 +00:00
record_chunks ( d ) ;
1995-05-04 03:51:22 +00:00
while ( chunking ) {
1995-05-01 21:56:32 +00:00
clear ( ) ;
1995-05-04 23:36:23 +00:00
print_chunks ( d ) ;
1995-05-04 03:51:22 +00:00
print_command_summary ( ) ;
if ( msg ) {
standout ( ) ; mvprintw ( 23 , 0 , msg ) ; standend ( ) ;
beep ( ) ;
msg = NULL ;
}
refresh ( ) ;
1995-05-04 19:48:19 +00:00
key = toupper ( getch ( ) ) ;
1995-05-04 03:51:22 +00:00
switch ( key ) {
case KEY_UP :
case ' - ' :
if ( current_chunk ! = 0 )
- - current_chunk ;
break ;
case KEY_DOWN :
case ' + ' :
case ' \r ' :
case ' \n ' :
if ( chunk_info [ current_chunk + 1 ] )
+ + current_chunk ;
break ;
case KEY_HOME :
current_chunk = 0 ;
break ;
case KEY_END :
while ( chunk_info [ current_chunk + 1 ] )
+ + current_chunk ;
break ;
case KEY_F ( 1 ) :
case ' ? ' :
systemDisplayFile ( " slice.hlp " ) ;
break ;
1995-05-04 23:36:23 +00:00
case ' A ' :
All_FreeBSD ( d ) ;
record_chunks ( d ) ;
break ;
1995-05-04 03:51:22 +00:00
case ' B ' :
if ( chunk_info [ current_chunk ] - > type ! = freebsd )
msg = " Can only scan for bad blocks in FreeBSD partition. " ;
1995-05-04 23:36:23 +00:00
else if ( strncmp ( name , " sd " , 2 ) | |
! msgYesNo ( " This typically makes sense only for ESDI, IDE or MFM drives. \n Are you sure you want to do this on a SCSI disk? " ) )
1995-05-04 03:51:22 +00:00
chunk_info [ current_chunk ] - > flags | = CHUNK_BAD144 ;
break ;
case ' C ' :
if ( chunk_info [ current_chunk ] - > type ! = unused )
msg = " Partition in use, delete it first or move to an unused one. " ;
else {
1995-05-05 23:47:47 +00:00
char * val , tmp [ 20 ] ;
1995-05-04 03:51:22 +00:00
int size ;
snprintf ( tmp , 20 , " %d " , chunk_info [ current_chunk ] - > size ) ;
val = msgGetInput ( tmp , " Please specify size for new FreeBSD partition " ) ;
1995-05-04 23:36:23 +00:00
if ( val & & ( size = strtol ( val , 0 , 0 ) ) > 0 ) {
1995-05-04 03:51:22 +00:00
Create_Chunk ( d , chunk_info [ current_chunk ] - > offset ,
size ,
freebsd ,
3 ,
1995-05-05 23:47:47 +00:00
( chunk_info [ current_chunk ] - > flags &
CHUNK_ALIGN ) ) ;
1995-05-04 23:36:23 +00:00
record_chunks ( d ) ;
1995-05-04 03:51:22 +00:00
}
}
break ;
case ' D ' :
if ( chunk_info [ current_chunk ] - > type = = unused )
msg = " Partition is already unused! " ;
else {
Delete_Chunk ( d , chunk_info [ current_chunk ] ) ;
1995-05-04 23:36:23 +00:00
record_chunks ( d ) ;
1995-05-04 03:51:22 +00:00
}
break ;
1995-05-08 01:27:07 +00:00
case ' G ' : {
char * val , geometry [ 80 ] ;
snprintf ( geometry , 80 , " %lu/%lu/%lu " ,
d - > bios_cyl , d - > bios_hd , d - > bios_sect ) ;
val = msgGetInput ( geometry ,
" Please specify the new geometry in cyl/hd/sect format. \n Don't forget to use the two slash (/) separator characters! \n It's not possible to parse the field without them. " ) ;
if ( val ) {
d - > bios_cyl = strtol ( val , & val , 0 ) ;
d - > bios_hd = strtol ( val + 1 , & val , 0 ) ;
d - > bios_sect = strtol ( val + 1 , 0 , 0 ) ;
}
}
1995-05-04 23:36:23 +00:00
break ;
1995-05-06 09:34:24 +00:00
case ' S ' :
/* Set Bootable */
1995-05-07 22:07:53 +00:00
chunk_info [ current_chunk ] - > flags | = CHUNK_ACTIVE ;
1995-05-06 09:34:24 +00:00
break ;
1995-05-04 03:51:22 +00:00
case ' U ' :
Free_Disk ( d ) ;
1995-05-04 23:36:23 +00:00
d = Open_Disk ( name ) ;
if ( ! d )
msgFatal ( " Can't reopen disk %s! " , name ) ;
record_chunks ( d ) ;
1995-05-04 03:51:22 +00:00
break ;
1995-05-04 19:48:19 +00:00
case ' W ' :
1995-05-04 23:36:23 +00:00
if ( ! msgYesNo ( " Are you sure you want to go into Wizard mode? \n No seat belts whatsoever are provided! " ) ) {
clear ( ) ;
dialog_clear ( ) ;
end_dialog ( ) ;
DialogActive = FALSE ;
slice_wizard ( d ) ;
clear ( ) ;
dialog_clear ( ) ;
DialogActive = TRUE ;
record_chunks ( d ) ;
}
1995-05-04 19:48:19 +00:00
else
1995-05-04 23:36:23 +00:00
msg = " Wise choice! " ;
1995-05-04 19:48:19 +00:00
break ;
1995-05-04 03:51:22 +00:00
case 27 : /* ESC */
chunking = FALSE ;
break ;
default :
1995-05-04 23:36:23 +00:00
beep ( ) ;
msg = " Type F1 or ? for help " ;
1995-05-04 03:51:22 +00:00
break ;
}
}
1995-05-04 23:36:23 +00:00
p = CheckRules ( d ) ;
if ( p ) {
msgConfirm ( p ) ;
free ( p ) ;
}
1995-05-04 03:51:22 +00:00
clear ( ) ;
refresh ( ) ;
return d ;
}
/*
* Create a menu listing all the devices in the system . The pass - in menu
* is expected to be a " prototype " from which the new menu is cloned .
*/
DMenu *
device_create_disk_menu ( DMenu * menu , Device * * rdevs , int ( * hook ) ( ) )
{
Device * devices ;
int numdevs ;
devices = device_get_all ( DEVICE_TYPE_DISK , & numdevs ) ;
* rdevs = devices ;
if ( ! devices ) {
msgConfirm ( " No devices suitable for installation found! \n \n Please verify that your disk controller (and attached drives) were detected properly. This can be done by selecting the ``Bootmsg'' option on the main menu and reviewing the boot messages carefully. " ) ;
return NULL ;
}
else {
Device * start ;
DMenu * tmp ;
int i ;
tmp = ( DMenu * ) safe_malloc ( sizeof ( DMenu ) +
( sizeof ( DMenuItem ) * ( numdevs + 1 ) ) ) ;
bcopy ( menu , tmp , sizeof ( DMenu ) ) ;
for ( start = devices , i = 0 ; start - > name [ 0 ] ; start + + , i + + ) {
tmp - > items [ i ] . title = start - > name ;
if ( ! strncmp ( start - > name , " sd " , 2 ) )
tmp - > items [ i ] . prompt = " SCSI disk " ;
else if ( ! strncmp ( start - > name , " wd " , 2 ) )
tmp - > items [ i ] . prompt = " IDE/ESDI/MFM/ST506 disk " ;
else
msgFatal ( " Unknown disk type: %s! " , start - > name ) ;
tmp - > items [ i ] . type = DMENU_CALL ;
tmp - > items [ i ] . ptr = hook ;
tmp - > items [ i ] . disabled = FALSE ;
}
tmp - > items [ i ] . type = DMENU_NOP ;
tmp - > items [ i ] . title = NULL ;
return tmp ;
1995-05-01 21:56:32 +00:00
}
}