2003-05-03 20:37:18 +04:00
/*
2001-06-01 08:20:26 +04:00
* misc / bximage . c
2006-06-16 11:29:33 +04:00
* $ Id : bximage . c , v 1.32 2006 - 06 - 16 07 : 29 : 33 vruppert Exp $
2001-06-01 07:30:40 +04:00
*
* Create empty hard disk or floppy disk images for bochs .
*
*/
2004-04-30 21:26:38 +04:00
# ifdef WIN32
# include <conio.h>
2004-08-19 20:03:03 +04:00
# include <windows.h>
# include <winioctl.h>
2004-08-19 23:42:22 +04:00
# ifdef _MSC_VER
# include <io.h>
# endif
2004-04-30 21:26:38 +04:00
# endif
2001-06-01 07:30:40 +04:00
# include <stdio.h>
# include <stdlib.h>
2001-06-01 09:11:45 +04:00
# include <string.h>
# include <ctype.h>
2001-06-01 07:30:40 +04:00
# include <assert.h>
# include "config.h"
2003-05-03 20:37:18 +04:00
# include <string.h>
2004-08-19 23:42:22 +04:00
# include "../osdep.h"
2005-11-06 14:07:01 +03:00
# define HDIMAGE_HEADERS_ONLY 1
# include "../iodev/hdimage.h"
2003-05-03 20:37:18 +04:00
2004-08-29 23:31:09 +04:00
int bx_hdimage ;
int bx_fdsize_idx ;
int bx_hdsize ;
int bx_hdimagemode ;
int bx_interactive ;
char bx_filename [ 256 ] ;
2004-08-19 20:03:03 +04:00
typedef int ( * WRITE_IMAGE ) ( FILE * , Bit64u ) ;
# ifdef WIN32
typedef int ( * WRITE_IMAGE_WIN32 ) ( HANDLE , Bit64u ) ;
# endif
2001-06-01 08:20:26 +04:00
char * EOF_ERR = " ERROR: End of input " ;
2006-06-16 11:29:33 +04:00
char * rcsid = " $Id: bximage.c,v 1.32 2006-06-16 07:29:33 vruppert Exp $ " ;
2001-06-01 08:20:26 +04:00
char * divider = " ======================================================================== " ;
2001-06-01 08:07:21 +04:00
2001-06-01 08:20:26 +04:00
/* menu data for choosing floppy/hard disk */
2003-05-03 20:37:18 +04:00
char * fdhd_menu = " \n Do you want to create a floppy disk image or a hard disk image? \n Please type hd or fd. " ;
2001-06-01 08:20:26 +04:00
char * fdhd_choices [ ] = { " fd " , " hd " } ;
int fdhd_n_choices = 2 ;
/* menu data for choosing floppy size */
2005-11-20 23:26:35 +03:00
char * fdsize_menu = " \n Choose the size of floppy disk image to create, in megabytes. \n Please type 0.16, 0.18, 0.32, 0.36, 0.72, 1.2, 1.44, 1.68, 1.72, or 2.88. \n " ;
char * fdsize_choices [ ] = { " 0.16 " , " 0.18 " , " 0.32 " , " 0.36 " , " 0.72 " , " 1.2 " , " 1.44 " , " 1.68 " , " 1.72 " , " 2.88 " } ;
int fdsize_n_choices = 10 ;
2001-06-01 08:20:26 +04:00
2003-05-03 20:37:18 +04:00
/* menu data for choosing disk mode */
2003-08-01 05:20:00 +04:00
char * hdmode_menu = " \n What kind of image should I create? \n Please type flat, sparse or growing. " ;
char * hdmode_choices [ ] = { " flat " , " sparse " , " growing " } ;
2003-05-03 20:37:18 +04:00
int hdmode_n_choices = 3 ;
2002-11-21 09:36:22 +03:00
void myexit ( int code )
{
# ifdef WIN32
printf ( " \n Press any key to continue \n " ) ;
getch ( ) ;
# endif
exit ( code ) ;
}
2001-06-01 08:20:26 +04:00
/* stolen from main.cc */
void bx_center_print ( FILE * file , char * line , int maxwidth )
{
int imax ;
int i ;
imax = ( maxwidth - strlen ( line ) ) > > 1 ;
for ( i = 0 ; i < imax ; i + + ) fputc ( ' ' , file ) ;
fputs ( line , file ) ;
}
void
print_banner ( )
{
printf ( " %s \n " , divider ) ;
bx_center_print ( stdout , " bximage \n " , 72 ) ;
bx_center_print ( stdout , " Disk Image Creation Tool for Bochs \n " , 72 ) ;
bx_center_print ( stdout , rcsid , 72 ) ;
printf ( " \n %s \n " , divider ) ;
}
/* this is how we crash */
void fatal ( char * c )
{
printf ( " %s \n " , c ) ;
2002-11-21 09:36:22 +03:00
myexit ( 1 ) ;
2001-06-01 08:20:26 +04:00
}
2004-08-29 23:31:09 +04:00
/* check if the argument string is present in the list -
returns index on success , - 1 on failure . */
int get_menu_index ( char * arg , int n_choices , char * choice [ ] )
{
int i ;
for ( i = 0 ; i < n_choices ; i + + ) {
if ( ! strcmp ( choice [ i ] , arg ) ) {
// matched, return the choice number
return i ;
}
}
return - 1 ;
}
2001-06-01 08:20:26 +04:00
/* remove leading spaces, newline junk at end. returns pointer to
cleaned string , which is between s0 and the null */
2001-06-01 07:30:40 +04:00
char *
clean_string ( char * s0 )
{
char * s = s0 ;
char * ptr ;
/* find first nonblank */
while ( isspace ( * s ) )
s + + ;
/* truncate string at first non-alphanumeric */
ptr = s ;
while ( isprint ( * ptr ) )
ptr + + ;
* ptr = 0 ;
return s ;
}
2001-06-01 08:20:26 +04:00
/* returns 0 on success, -1 on failure. The value goes into out. */
int
ask_int ( char * prompt , int min , int max , int the_default , int * out )
2001-06-01 07:30:40 +04:00
{
int n = max + 1 ;
char buffer [ 1024 ] ;
char * clean ;
int illegal ;
while ( 1 ) {
printf ( " %s " , prompt ) ;
2003-05-03 20:37:18 +04:00
printf ( " [%d] " , the_default ) ;
2001-06-01 07:30:40 +04:00
if ( ! fgets ( buffer , sizeof ( buffer ) , stdin ) )
return - 1 ;
clean = clean_string ( buffer ) ;
if ( strlen ( clean ) < 1 ) {
// empty line, use the default
* out = the_default ;
return 0 ;
}
illegal = ( 1 ! = sscanf ( buffer , " %d " , & n ) ) ;
if ( illegal | | n < min | | n > max ) {
printf ( " Your choice (%s) was not an integer between %d and %d. \n \n " ,
clean , min , max ) ;
} else {
// choice is okay
* out = n ;
return 0 ;
}
}
}
2001-06-01 08:20:26 +04:00
int
ask_menu ( char * prompt , int n_choices , char * choice [ ] , int the_default , int * out )
2001-06-01 07:30:40 +04:00
{
char buffer [ 1024 ] ;
char * clean ;
int i ;
* out = - 1 ;
while ( 1 ) {
printf ( " %s " , prompt ) ;
2003-05-03 20:37:18 +04:00
printf ( " [%s] " , choice [ the_default ] ) ;
2001-06-01 07:30:40 +04:00
if ( ! fgets ( buffer , sizeof ( buffer ) , stdin ) )
return - 1 ;
clean = clean_string ( buffer ) ;
if ( strlen ( clean ) < 1 ) {
// empty line, use the default
* out = the_default ;
return 0 ;
}
for ( i = 0 ; i < n_choices ; i + + ) {
2001-06-01 09:45:55 +04:00
if ( ! strcmp ( choice [ i ] , clean ) ) {
2001-06-01 07:30:40 +04:00
// matched, return the choice number
* out = i ;
return 0 ;
}
}
printf ( " Your choice (%s) did not match any of the choices: \n " , clean ) ;
for ( i = 0 ; i < n_choices ; i + + ) {
if ( i > 0 ) printf ( " , " ) ;
printf ( " %s " , choice [ i ] ) ;
}
printf ( " \n " ) ;
}
}
2001-06-01 08:20:26 +04:00
int
ask_yn ( char * prompt , int the_default , int * out )
2001-06-01 08:07:21 +04:00
{
char buffer [ 16 ] ;
char * clean ;
* out = - 1 ;
while ( 1 ) {
printf ( " %s " , prompt ) ;
2003-05-03 20:37:18 +04:00
printf ( " [%s] " , the_default ? " yes " : " no " ) ;
2001-06-01 08:07:21 +04:00
if ( ! fgets ( buffer , sizeof ( buffer ) , stdin ) )
return - 1 ;
clean = clean_string ( buffer ) ;
if ( strlen ( clean ) < 1 ) {
// empty line, use the default
* out = the_default ;
return 0 ;
}
switch ( tolower ( clean [ 0 ] ) ) {
case ' y ' : * out = 1 ; return 0 ;
case ' n ' : * out = 0 ; return 0 ;
}
printf ( " Please type either yes or no. \n " ) ;
}
}
2001-06-01 08:20:26 +04:00
int
ask_string ( char * prompt , char * the_default , char * out )
2001-06-01 07:30:40 +04:00
{
char buffer [ 1024 ] ;
char * clean ;
out [ 0 ] = 0 ;
printf ( " %s " , prompt ) ;
2003-05-03 20:37:18 +04:00
printf ( " [%s] " , the_default ) ;
2001-06-01 07:30:40 +04:00
if ( ! fgets ( buffer , sizeof ( buffer ) , stdin ) )
return - 1 ;
clean = clean_string ( buffer ) ;
if ( strlen ( clean ) < 1 ) {
// empty line, use the default
strcpy ( out , the_default ) ;
return 0 ;
}
strcpy ( out , clean ) ;
return 0 ;
}
2003-05-03 20:37:18 +04:00
// fileset is like memset but for a file handle
void fileset ( FILE * fp , int c , size_t n )
{
# define BLOCK_SIZE (1024)
int block [ BLOCK_SIZE ] ;
size_t left_to_write = n ;
memset ( block , c , sizeof ( block ) ) ;
while ( left_to_write > 0 )
{
size_t write = sizeof ( block ) ;
if ( write > left_to_write ) write = left_to_write ;
if ( 1 ! = fwrite ( block , write , 1 , fp ) )
{
fclose ( fp ) ;
fatal ( " ERROR: The disk image is not complete - could not write data block! " ) ;
}
left_to_write - = write ;
}
}
/* Create a suited redolog header */
void make_redolog_header ( redolog_header_t * header , const char * type , Bit64u size )
{
Bit32u entries , extent_size , bitmap_size ;
Bit64u maxsize ;
// Set standard header values
strcpy ( ( char * ) header - > standard . magic , STANDARD_HEADER_MAGIC ) ;
strcpy ( ( char * ) header - > standard . type , REDOLOG_TYPE ) ;
strcpy ( ( char * ) header - > standard . subtype , type ) ;
header - > standard . version = htod32 ( STANDARD_HEADER_VERSION ) ;
header - > standard . header = htod32 ( STANDARD_HEADER_SIZE ) ;
entries = 512 ;
bitmap_size = 1 ;
// Compute #entries and extent size values
do {
static Bit32u flip = 0 ;
extent_size = 8 * bitmap_size * 512 ;
header - > specific . catalog = htod32 ( entries ) ;
header - > specific . bitmap = htod32 ( bitmap_size ) ;
header - > specific . extent = htod32 ( extent_size ) ;
maxsize = ( Bit64u ) entries * ( Bit64u ) extent_size ;
flip + + ;
if ( flip & 0x01 ) bitmap_size * = 2 ;
else entries * = 2 ;
} while ( maxsize < size ) ;
header - > specific . disk = htod64 ( size ) ;
}
/* produce a flat image file */
2004-08-19 20:03:03 +04:00
# ifdef WIN32
int make_flat_image_win32 ( HANDLE hFile , Bit64u sec )
{
LARGE_INTEGER pos ;
2005-11-06 14:07:01 +03:00
DWORD dwCount , errCode ;
2004-08-19 20:03:03 +04:00
USHORT mode ;
char buffer [ 1024 ] ;
SetLastError ( NO_ERROR ) ;
mode = COMPRESSION_FORMAT_DEFAULT ;
dwCount = 0 ;
memset ( buffer , 0 , 512 ) ;
WriteFile ( hFile , buffer , 512 , & dwCount , NULL ) ; // set the first sector to 0, Win98 doesn't zero out the file
// if there is a write at/over the end
DeviceIoControl ( hFile , FSCTL_SET_COMPRESSION , & mode , sizeof ( mode ) , NULL , 0 , & dwCount , NULL ) ;
2005-06-04 21:44:59 +04:00
pos . u . LowPart = ( unsigned long ) ( ( sec - 1 ) < < 9 ) ;
pos . u . HighPart = ( unsigned long ) ( ( sec - 1 ) > > 23 ) ;
2004-08-19 20:03:03 +04:00
pos . u . LowPart = SetFilePointer ( hFile , pos . u . LowPart , & pos . u . HighPart , FILE_BEGIN ) ;
memset ( buffer , 0 , 512 ) ;
if ( ( pos . u . LowPart = = 0xffffffff & & GetLastError ( ) ! = NO_ERROR ) | | ! WriteFile ( hFile , buffer , 512 , & dwCount , NULL ) | | dwCount ! = 512 )
{
2005-11-06 14:07:01 +03:00
errCode = GetLastError ( ) ;
2004-08-19 20:03:03 +04:00
CloseHandle ( hFile ) ;
2005-11-06 14:07:01 +03:00
if ( errCode = = ERROR_DISK_FULL ) {
fatal ( " \n ERROR: Not enough space on disk for image! " ) ;
} else {
sprintf ( buffer , " \n ERROR: Disk image creation failed with error code %i! " , errCode ) ;
fatal ( buffer ) ;
}
2004-08-19 20:03:03 +04:00
}
return 0 ;
}
# endif
2003-05-03 20:37:18 +04:00
int make_flat_image ( FILE * fp , Bit64u sec )
{
/*
* seek to sec * 512 - 1 and write a single character .
* can ' t just do : fseek ( fp , 512 * sec - 1 , SEEK_SET )
* because 512 * sec may be too large for signed int .
*/
while ( sec > 0 )
{
/* temp <-- min(sec, 4194303)
* 4194303 is ( int ) ( 0x7FFFFFFF / 512 )
*/
2005-06-04 21:44:59 +04:00
long temp = ( long ) ( ( sec < 4194303 ) ? sec : 4194303 ) ;
2003-05-03 20:37:18 +04:00
fseek ( fp , 512 * temp , SEEK_CUR ) ;
sec - = temp ;
}
fseek ( fp , - 1 , SEEK_CUR ) ;
if ( fputc ( ' \0 ' , fp ) = = EOF )
{
fclose ( fp ) ;
2005-11-06 14:07:01 +03:00
fatal ( " \n ERROR: The disk image is not complete! (image larger then free space?) " ) ;
2003-05-03 20:37:18 +04:00
}
return 0 ;
}
/* produce a sparse image file */
int make_sparse_image ( FILE * fp , Bit64u sec )
{
Bit64u numpages ;
sparse_header_t header ;
size_t sizesofar ;
size_t padtopagesize ;
memset ( & header , 0 , sizeof ( header ) ) ;
header . magic = htod32 ( SPARSE_HEADER_MAGIC ) ;
header . version = htod32 ( SPARSE_HEADER_VERSION ) ;
header . pagesize = htod32 ( ( 1 < < 10 ) * 32 ) ; // Use 32 KB Pages - could be configurable
numpages = ( sec / ( dtoh32 ( header . pagesize ) / 512 ) ) + 1 ;
2005-06-04 21:44:59 +04:00
header . numpages = htod32 ( ( Bit32u ) numpages ) ;
2006-06-16 11:29:33 +04:00
header . disk = htod64 ( sec * 512 ) ;
2003-05-03 20:37:18 +04:00
if ( numpages ! = dtoh32 ( header . numpages ) )
{
fclose ( fp ) ;
fatal ( " ERROR: The disk image is too large for a sparse image! " ) ;
// Could increase page size here.
// But note this only happens at 128 Terabytes!
}
if ( fwrite ( & header , sizeof ( header ) , 1 , fp ) ! = 1 )
{
fclose ( fp ) ;
fatal ( " ERROR: The disk image is not complete - could not write header! " ) ;
}
fileset ( fp , 0xff , 4 * dtoh32 ( header . numpages ) ) ;
sizesofar = SPARSE_HEADER_SIZE + ( 4 * dtoh32 ( header . numpages ) ) ;
padtopagesize = dtoh32 ( header . pagesize ) - ( sizesofar & ( dtoh32 ( header . pagesize ) - 1 ) ) ;
fileset ( fp , 0 , padtopagesize ) ;
return 0 ;
}
2003-08-01 05:20:00 +04:00
/* produce a growing image file */
int make_growing_image ( FILE * fp , Bit64u sec )
2003-05-03 20:37:18 +04:00
{
redolog_header_t header ;
Bit32u i , not_allocated = htod32 ( REDOLOG_PAGE_NOT_ALLOCATED ) ;
memset ( & header , 0 , sizeof ( header ) ) ;
2003-08-01 05:20:00 +04:00
make_redolog_header ( & header , REDOLOG_SUBTYPE_GROWING , sec * 512 ) ;
2003-05-03 20:37:18 +04:00
if ( fwrite ( & header , sizeof ( header ) , 1 , fp ) ! = 1 )
{
fclose ( fp ) ;
fatal ( " ERROR: The disk image is not complete - could not write header! " ) ;
}
for ( i = 0 ; i < dtoh32 ( header . specific . catalog ) ; i + + )
{
if ( fwrite ( & not_allocated , sizeof ( Bit32u ) , 1 , fp ) ! = 1 )
{
fclose ( fp ) ;
fatal ( " ERROR: The disk image is not complete - could not write catalog! " ) ;
}
}
return 0 ;
}
2001-06-01 08:20:26 +04:00
/* produce the image file */
2004-08-19 20:03:03 +04:00
# ifdef WIN32
int make_image_win32 ( Bit64u sec , char * filename , WRITE_IMAGE_WIN32 write_image )
2001-06-01 07:30:40 +04:00
{
2004-08-19 20:03:03 +04:00
HANDLE hFile ;
char buffer [ 1024 ] ;
// check if it exists before trashing someone's disk image
hFile = CreateFile ( filename , GENERIC_READ , 0 , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL ) ;
if ( hFile ! = INVALID_HANDLE_VALUE ) {
int confirm ;
sprintf ( buffer , " \n The disk image '%s' already exists. Are you sure you want to replace it? \n Please type yes or no. " , filename ) ;
if ( ask_yn ( buffer , 0 , & confirm ) < 0 )
fatal ( EOF_ERR ) ;
if ( ! confirm )
fatal ( " ERROR: Aborted " ) ;
CloseHandle ( hFile ) ;
}
// okay, now open it for writing
hFile = CreateFile ( filename , GENERIC_WRITE | GENERIC_READ , 0 , NULL , CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL ) ;
if ( hFile = = INVALID_HANDLE_VALUE ) {
// attempt to print an error
# ifdef HAVE_PERROR
sprintf ( buffer , " while opening '%s' for writing " , filename ) ;
perror ( buffer ) ;
# endif
fatal ( " ERROR: Could not write disk image " ) ;
}
printf ( " \n Writing: [ " ) ;
if ( ( * write_image ) ( hFile , sec ) ! = 0 )
fatal ( " ERROR: while writing disk image! " ) ;
printf ( " ] Done. \n " ) ;
CloseHandle ( hFile ) ;
return 0 ;
}
# endif
int make_image ( Bit64u sec , char * filename , WRITE_IMAGE write_image )
{
FILE * fp ;
2001-06-01 07:30:40 +04:00
char buffer [ 1024 ] ;
2003-05-03 20:37:18 +04:00
2001-06-01 08:07:21 +04:00
// check if it exists before trashing someone's disk image
fp = fopen ( filename , " r " ) ;
if ( fp ) {
int confirm ;
2003-05-03 20:37:18 +04:00
sprintf ( buffer , " \n The disk image '%s' already exists. Are you sure you want to replace it? \n Please type yes or no. " , filename ) ;
2001-06-01 08:07:21 +04:00
if ( ask_yn ( buffer , 0 , & confirm ) < 0 )
fatal ( EOF_ERR ) ;
2003-05-03 20:37:18 +04:00
if ( ! confirm )
2001-06-01 08:07:21 +04:00
fatal ( " ERROR: Aborted " ) ;
fclose ( fp ) ;
}
// okay, now open it for writing
fp = fopen ( filename , " w " ) ;
2001-06-01 07:30:40 +04:00
if ( fp = = NULL ) {
// attempt to print an error
# ifdef HAVE_PERROR
sprintf ( buffer , " while opening '%s' for writing " , filename ) ;
perror ( buffer ) ;
# endif
2001-06-01 08:07:21 +04:00
fatal ( " ERROR: Could not write disk image " ) ;
2001-06-01 07:30:40 +04:00
}
2002-05-21 11:23:09 +04:00
2001-06-01 08:20:26 +04:00
printf ( " \n Writing: [ " ) ;
2002-05-21 11:23:09 +04:00
2003-05-03 20:37:18 +04:00
if ( ( * write_image ) ( fp , sec ) ! = 0 )
fatal ( " ERROR: while writing disk image! " ) ;
2002-05-21 11:23:09 +04:00
2001-06-01 08:20:26 +04:00
printf ( " ] Done. \n " ) ;
2001-06-01 07:30:40 +04:00
fclose ( fp ) ;
return 0 ;
}
2004-08-29 23:31:09 +04:00
void print_usage ( )
{
fprintf ( stderr ,
" Usage: bximage [options] [filename] \n \n "
" Supported options: \n "
" -fd create floppy image \n "
" -hd create hard disk image \n "
" -mode=... image mode (hard disks only) \n "
" -size=... image size in megabytes \n "
" -q quiet mode (don't prompt for user input) \n "
" --help display this help and exit \n \n " ) ;
}
int parse_cmdline ( int argc , char * argv [ ] )
{
int arg = 1 ;
int ret = 1 ;
bx_hdimage = - 1 ;
bx_fdsize_idx = - 1 ;
bx_hdsize = - 1 ;
bx_hdimagemode = - 1 ;
bx_interactive = 1 ;
bx_filename [ 0 ] = 0 ;
while ( ( arg < argc ) & & ( ret = = 1 ) ) {
// parse next arg
if ( ! strcmp ( " --help " , argv [ arg ] ) | | ! strncmp ( " /? " , argv [ arg ] , 2 ) ) {
print_usage ( ) ;
ret = 0 ;
}
else if ( ! strcmp ( " -fd " , argv [ arg ] ) ) {
bx_hdimage = 0 ;
bx_hdimagemode = 0 ;
}
else if ( ! strcmp ( " -hd " , argv [ arg ] ) ) {
bx_hdimage = 1 ;
bx_fdsize_idx = 0 ;
}
else if ( ! strncmp ( " -mode= " , argv [ arg ] , 6 ) ) {
if ( bx_hdimage = = 1 ) {
bx_hdimagemode = get_menu_index ( & argv [ arg ] [ 6 ] , hdmode_n_choices , hdmode_choices ) ;
if ( bx_hdimagemode < 0 ) {
printf ( " Unknown image mode: %s \n \n " , & argv [ arg ] [ 6 ] ) ;
ret = 0 ;
}
} else {
printf ( " Image mode option only supported for hard disks \n \n " ) ;
ret = 0 ;
}
}
else if ( ! strncmp ( " -size= " , argv [ arg ] , 6 ) ) {
if ( bx_hdimage = = 0 ) {
bx_fdsize_idx = get_menu_index ( & argv [ arg ] [ 6 ] , fdsize_n_choices , fdsize_choices ) ;
if ( bx_fdsize_idx < 0 ) {
printf ( " Unknown floppy image size: %s \n \n " , & argv [ arg ] [ 6 ] ) ;
ret = 0 ;
}
} else if ( bx_hdimage = = 1 ) {
if ( sscanf ( & argv [ arg ] [ 6 ] , " %d " , & bx_hdsize ) ! = 1 ) {
printf ( " Error in hard disk image size argument: %s \n \n " , & argv [ arg ] [ 6 ] ) ;
ret = 0 ;
} else if ( ( bx_hdsize < 1 ) | | ( bx_hdsize > 32255 ) ) {
printf ( " Hard disk image size out of range \n \n " ) ;
ret = 0 ;
}
} else {
printf ( " Image type (fd/hd) not specified \n \n " ) ;
}
}
else if ( ! strcmp ( " -q " , argv [ arg ] ) ) {
bx_interactive = 0 ;
}
else if ( argv [ arg ] [ 0 ] = = ' - ' ) {
printf ( " Unknown option: %s \n \n " , argv [ arg ] ) ;
ret = 0 ;
} else {
strcpy ( bx_filename , argv [ arg ] ) ;
}
arg + + ;
}
if ( bx_hdimage = = - 1 ) {
bx_hdimage = 1 ;
2005-11-20 23:26:35 +03:00
bx_fdsize_idx = 6 ;
2004-08-29 23:31:09 +04:00
bx_interactive = 1 ;
}
if ( bx_hdimage = = 1 ) {
if ( bx_hdimagemode = = - 1 ) {
bx_hdimagemode = 0 ;
bx_interactive = 1 ;
}
if ( bx_hdsize = = - 1 ) {
bx_hdsize = 10 ;
bx_interactive = 1 ;
}
} else {
if ( bx_fdsize_idx = = - 1 ) {
2005-11-20 23:26:35 +03:00
bx_fdsize_idx = 6 ;
2004-08-29 23:31:09 +04:00
bx_interactive = 1 ;
}
}
if ( ! strlen ( bx_filename ) ) {
bx_interactive = 1 ;
}
return ret ;
}
int main ( int argc , char * argv [ ] )
2001-06-01 07:30:40 +04:00
{
2002-11-15 21:14:08 +03:00
Bit64s sectors = 0 ;
2001-06-01 07:30:40 +04:00
char filename [ 256 ] ;
char bochsrc_line [ 256 ] ;
2003-05-03 20:37:18 +04:00
2004-08-19 20:03:03 +04:00
WRITE_IMAGE write_function = NULL ;
# ifdef WIN32
WRITE_IMAGE_WIN32 writefn_win32 = NULL ;
# endif
2003-05-03 20:37:18 +04:00
2004-08-29 23:31:09 +04:00
if ( ! parse_cmdline ( argc , argv ) )
myexit ( 1 ) ;
2001-06-01 08:20:26 +04:00
print_banner ( ) ;
2004-08-29 23:31:09 +04:00
if ( bx_interactive ) {
if ( ask_menu ( fdhd_menu , fdhd_n_choices , fdhd_choices , bx_hdimage , & bx_hdimage ) < 0 )
fatal ( EOF_ERR ) ;
}
if ( bx_hdimage ) {
2005-11-06 19:50:30 +03:00
unsigned int cyl ;
int hdsize , heads = 16 , spt = 63 ;
2003-05-03 20:37:18 +04:00
int mode ;
2004-08-29 23:31:09 +04:00
if ( bx_interactive ) {
if ( ask_menu ( hdmode_menu , hdmode_n_choices , hdmode_choices , bx_hdimagemode , & mode ) < 0 )
fatal ( EOF_ERR ) ;
2005-11-06 19:50:30 +03:00
if ( ask_int ( " \n Enter the hard disk size in megabytes, between 1 and 129023 \n " , 1 , 129023 , bx_hdsize , & hdsize ) < 0 )
2004-08-29 23:31:09 +04:00
fatal ( EOF_ERR ) ;
} else {
mode = bx_hdimagemode ;
hdsize = bx_hdsize ;
}
2005-11-06 19:50:30 +03:00
cyl = ( unsigned int ) ( hdsize * 1024.0 * 1024.0 / 16.0 / 63.0 / 512.0 ) ;
assert ( cyl < 262144 ) ;
2001-06-01 07:30:40 +04:00
sectors = cyl * heads * spt ;
2003-05-03 20:37:18 +04:00
printf ( " \n I will create a '%s' hard disk image with \n " , hdmode_choices [ mode ] ) ;
2001-06-01 07:30:40 +04:00
printf ( " cyl=%d \n " , cyl ) ;
printf ( " heads=%d \n " , heads ) ;
printf ( " sectors per track=%d \n " , spt ) ;
2004-08-19 23:42:22 +04:00
printf ( " total sectors= " FMT_LL " d \n " , sectors ) ;
2004-08-19 20:03:03 +04:00
printf ( " total size=%.2f megabytes \n " , ( float ) ( Bit64s ) ( sectors / 2 ) / 1024.0 ) ;
2004-08-29 23:31:09 +04:00
if ( bx_interactive ) {
if ( ! strlen ( bx_filename ) ) strcpy ( bx_filename , " c.img " ) ;
if ( ask_string ( " \n What should I name the image? \n " , bx_filename , filename ) < 0 )
fatal ( EOF_ERR ) ;
} else {
strcpy ( filename , bx_filename ) ;
}
2003-05-03 20:37:18 +04:00
sprintf ( bochsrc_line , " ata0-master: type=disk, path= \" %s \" , mode=%s, cylinders=%d, heads=%d, spt=%d " , filename , hdmode_choices [ mode ] , cyl , heads , spt ) ;
switch ( mode ) {
case 1 :
write_function = make_sparse_image ;
break ;
case 2 :
2003-08-01 05:20:00 +04:00
write_function = make_growing_image ;
2003-05-03 20:37:18 +04:00
break ;
default :
2004-08-19 20:03:03 +04:00
# ifdef WIN32
writefn_win32 = make_flat_image_win32 ;
# else
2003-05-03 20:37:18 +04:00
write_function = make_flat_image ;
2004-08-19 20:03:03 +04:00
# endif
2003-05-03 20:37:18 +04:00
}
2001-06-01 07:30:40 +04:00
} else {
2001-06-01 09:11:45 +04:00
int fdsize , cyl = 0 , heads = 0 , spt = 0 ;
2004-08-29 23:31:09 +04:00
if ( bx_interactive ) {
if ( ask_menu ( fdsize_menu , fdsize_n_choices , fdsize_choices , bx_fdsize_idx , & fdsize ) < 0 )
fatal ( EOF_ERR ) ;
} else {
fdsize = bx_fdsize_idx ;
}
2001-06-01 07:30:40 +04:00
switch ( fdsize ) {
2005-11-20 23:26:35 +03:00
case 0 : cyl = 40 ; heads = 1 ; spt = 8 ; break ; /* 0.16 meg */
case 1 : cyl = 40 ; heads = 1 ; spt = 9 ; break ; /* 0.18 meg */
case 2 : cyl = 40 ; heads = 2 ; spt = 8 ; break ; /* 0.32 meg */
case 3 : cyl = 40 ; heads = 2 ; spt = 9 ; break ; /* 0.36 meg */
case 4 : cyl = 80 ; heads = 2 ; spt = 9 ; break ; /* 0.72 meg */
case 5 : cyl = 80 ; heads = 2 ; spt = 15 ; break ; /* 1.2 meg */
case 6 : cyl = 80 ; heads = 2 ; spt = 18 ; break ; /* 1.44 meg */
case 7 : cyl = 80 ; heads = 2 ; spt = 21 ; break ; /* 1.68 meg */
case 8 : cyl = 82 ; heads = 2 ; spt = 21 ; break ; /* 1.72 meg */
case 9 : cyl = 80 ; heads = 2 ; spt = 36 ; break ; /* 2.88 meg */
default :
fatal ( " ERROR: fdsize out of range " ) ;
2001-06-01 07:30:40 +04:00
}
sectors = cyl * heads * spt ;
printf ( " I will create a floppy image with \n " ) ;
printf ( " cyl=%d \n " , cyl ) ;
printf ( " heads=%d \n " , heads ) ;
printf ( " sectors per track=%d \n " , spt ) ;
2004-08-19 23:42:22 +04:00
printf ( " total sectors= " FMT_LL " d \n " , sectors ) ;
printf ( " total bytes= " FMT_LL " d \n " , sectors * 512 ) ;
2004-08-29 23:31:09 +04:00
if ( bx_interactive ) {
if ( ! strlen ( bx_filename ) ) strcpy ( bx_filename , " a.img " ) ;
if ( ask_string ( " \n What should I name the image? \n " , bx_filename , filename ) < 0 )
fatal ( EOF_ERR ) ;
} else {
strcpy ( filename , bx_filename ) ;
}
2005-11-20 23:26:35 +03:00
sprintf ( bochsrc_line , " floppya: image= \" %s \" , status=inserted " , filename ) ;
2003-05-03 20:37:18 +04:00
write_function = make_flat_image ;
2001-06-01 07:30:40 +04:00
}
if ( sectors < 1 )
2001-06-01 08:07:21 +04:00
fatal ( " ERROR: Illegal disk size! " ) ;
2001-06-01 07:30:40 +04:00
if ( strlen ( filename ) < 1 )
2001-06-01 08:07:21 +04:00
fatal ( " ERROR: Illegal filename " ) ;
2004-08-19 20:03:03 +04:00
# ifdef WIN32
if ( writefn_win32 ! = NULL ) {
make_image_win32 ( sectors , filename , writefn_win32 ) ;
}
else
2004-08-24 15:42:18 +04:00
# endif
2004-08-19 20:03:03 +04:00
{
make_image ( sectors , filename , write_function ) ;
}
2004-08-24 15:42:18 +04:00
printf ( " \n I wrote " FMT_LL " u bytes to " , sectors * 512 ) ;
printf ( " %s. \n " , filename ) ;
2001-06-01 07:30:40 +04:00
printf ( " \n The following line should appear in your bochsrc: \n " ) ;
printf ( " %s \n " , bochsrc_line ) ;
2004-04-30 21:26:38 +04:00
# ifdef WIN32
if ( OpenClipboard ( NULL ) ) {
HGLOBAL hgClip ;
EmptyClipboard ( ) ;
hgClip = GlobalAlloc ( GMEM_DDESHARE , ( strlen ( bochsrc_line ) + 1 ) ) ;
strcpy ( ( char * ) GlobalLock ( hgClip ) , bochsrc_line ) ;
GlobalUnlock ( hgClip ) ;
SetClipboardData ( CF_TEXT , hgClip ) ;
CloseClipboard ( ) ;
2005-01-28 13:25:06 +03:00
printf ( " (The line is stored in your windows clipboard, use CTRL-V to paste) \n " ) ;
2004-04-30 21:26:38 +04:00
}
# endif
2002-11-21 09:36:22 +03:00
myexit ( 0 ) ;
2002-11-26 14:21:31 +03:00
// make picky compilers (c++, gcc) happy,
2003-05-03 20:37:18 +04:00
// even though we leave via 'myexit' just above
2002-11-26 14:21:31 +03:00
return 0 ;
2001-06-01 07:30:40 +04:00
}