Revision 42550fde vl.c
b/vl.c | ||
---|---|---|
109 | 109 |
/* XXX: use a two level table to limit memory usage */ |
110 | 110 |
#define MAX_IOPORTS 65536 |
111 | 111 |
|
112 |
#define DISK_OPTIONS_SIZE 256 |
|
113 |
|
|
112 | 114 |
const char *bios_dir = CONFIG_QEMU_SHAREDIR; |
113 | 115 |
char phys_ram_file[1024]; |
114 | 116 |
void *ioport_opaque[MAX_IOPORTS]; |
... | ... | |
119 | 121 |
BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD]; |
120 | 122 |
/* point to the block driver where the snapshots are managed */ |
121 | 123 |
BlockDriverState *bs_snapshots; |
124 |
BlockDriverState *bs_scsi_table[MAX_SCSI_DISKS]; |
|
125 |
SCSIDiskInfo scsi_disks_info[MAX_SCSI_DISKS]; |
|
126 |
int scsi_hba_lsi; /* Count of scsi disks/cdrom using this lsi adapter */ |
|
122 | 127 |
int vga_ram_size; |
123 | 128 |
int bios_size; |
124 | 129 |
static DisplayState display_state; |
... | ... | |
3814 | 3819 |
term_printf(" %s\n", vc->info_str); |
3815 | 3820 |
} |
3816 | 3821 |
} |
3817 |
|
|
3822 |
|
|
3823 |
/* Parse IDE and SCSI disk options */ |
|
3824 |
static int disk_options_init(int num_ide_disks, |
|
3825 |
char ide_disk_options[][DISK_OPTIONS_SIZE], |
|
3826 |
int snapshot, |
|
3827 |
int num_scsi_disks, |
|
3828 |
char scsi_disk_options[][DISK_OPTIONS_SIZE], |
|
3829 |
int cdrom_index, |
|
3830 |
int cyls, |
|
3831 |
int heads, |
|
3832 |
int secs, |
|
3833 |
int translation) |
|
3834 |
{ |
|
3835 |
char buf[256]; |
|
3836 |
char dev_name[64]; |
|
3837 |
int id, i, j; |
|
3838 |
int cdrom_device; |
|
3839 |
int ide_cdrom_created = 0; |
|
3840 |
int scsi_index; |
|
3841 |
scsi_host_adapters temp_adapter; |
|
3842 |
|
|
3843 |
/* Process any IDE disks/cdroms */ |
|
3844 |
for (i=0; i< num_ide_disks; i++) { |
|
3845 |
for (j=0; j<MAX_DISKS; j++) { |
|
3846 |
if (ide_disk_options[j][0] == '\0') |
|
3847 |
continue; |
|
3848 |
|
|
3849 |
if (get_param_value(buf, sizeof(buf),"type",ide_disk_options[j])) { |
|
3850 |
if (!strcmp(buf, "disk")) { |
|
3851 |
cdrom_device = 0; |
|
3852 |
} else if (!strcmp(buf, "cdrom")) { |
|
3853 |
cdrom_device = 1; |
|
3854 |
ide_cdrom_created = 1; |
|
3855 |
} else { |
|
3856 |
fprintf(stderr, "qemu: invalid IDE disk type= value: %s\n", buf); |
|
3857 |
return -1; |
|
3858 |
} |
|
3859 |
} else { |
|
3860 |
cdrom_device = 0; |
|
3861 |
} |
|
3862 |
|
|
3863 |
if (cdrom_device) { |
|
3864 |
snprintf(dev_name, sizeof(dev_name), "cdrom%c", i); |
|
3865 |
} else { |
|
3866 |
snprintf(dev_name, sizeof(dev_name), "hd%c", i + 'a'); |
|
3867 |
} |
|
3868 |
|
|
3869 |
if (!(get_param_value(buf, sizeof(buf),"img",ide_disk_options[j]))) { |
|
3870 |
fprintf(stderr, "qemu: missing IDE disk img= value.\n"); |
|
3871 |
return -1; |
|
3872 |
} |
|
3873 |
|
|
3874 |
if (!(bs_table[i] = bdrv_new(dev_name))) { |
|
3875 |
fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name); |
|
3876 |
return -1; |
|
3877 |
} |
|
3878 |
|
|
3879 |
if (cdrom_device) { |
|
3880 |
bdrv_set_type_hint(bs_table[i], BDRV_TYPE_CDROM); |
|
3881 |
} |
|
3882 |
|
|
3883 |
if (bdrv_open(bs_table[i], buf, snapshot ? BDRV_O_SNAPSHOT : 0) < 0) { |
|
3884 |
fprintf(stderr, "qemu: could not open hard disk image: '%s'\n", |
|
3885 |
buf); |
|
3886 |
return -1; |
|
3887 |
} |
|
3888 |
if (i == 0 && cyls != 0) { |
|
3889 |
bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs); |
|
3890 |
bdrv_set_translation_hint(bs_table[i], translation); |
|
3891 |
} |
|
3892 |
ide_disk_options[j][0] = '\0'; |
|
3893 |
|
|
3894 |
if (i == cdrom_index) { |
|
3895 |
cdrom_index = -1; |
|
3896 |
} |
|
3897 |
break; /* finished with this IDE device*/ |
|
3898 |
} |
|
3899 |
} |
|
3900 |
|
|
3901 |
if (cdrom_index >= 0 && (!ide_cdrom_created)) { |
|
3902 |
bs_table[cdrom_index] = bdrv_new("cdrom"); |
|
3903 |
bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM); |
|
3904 |
} |
|
3905 |
|
|
3906 |
for(i = 0; i < num_scsi_disks; i++) { |
|
3907 |
|
|
3908 |
temp_adapter = SCSI_LSI_53C895A; |
|
3909 |
scsi_hba_lsi++; |
|
3910 |
|
|
3911 |
/*Check for sdx= parameter */ |
|
3912 |
if (get_param_value(buf, sizeof(buf), "sdx", scsi_disk_options[i])) { |
|
3913 |
if (buf[0] >= 'a' && buf[0] <= 'g') { |
|
3914 |
scsi_index = buf[0] - 'a'; |
|
3915 |
} else{ |
|
3916 |
fprintf(stderr, "qemu: sdx= option for SCSI must be one letter from a-g. %s \n",buf); |
|
3917 |
exit(1); |
|
3918 |
} |
|
3919 |
} else { |
|
3920 |
scsi_index = 0; |
|
3921 |
} |
|
3922 |
|
|
3923 |
/* Check for SCSI id specified. */ |
|
3924 |
if (get_param_value(buf, sizeof(buf),"id",scsi_disk_options[i])) { |
|
3925 |
id = strtol(buf, NULL, 0); |
|
3926 |
if (id < 0 || id > 6) { |
|
3927 |
fprintf(stderr, "qemu: SCSI id must be from 0-6: %d\n", id); |
|
3928 |
return -1; |
|
3929 |
} |
|
3930 |
/* Check if id already used */ |
|
3931 |
for(j = 0; j < MAX_SCSI_DISKS; j++) { |
|
3932 |
if (scsi_disks_info[j].device_type != SCSI_NONE && |
|
3933 |
j != i && |
|
3934 |
scsi_disks_info[j].adapter == temp_adapter && |
|
3935 |
scsi_disks_info[j].id == id ) { |
|
3936 |
fprintf(stderr, "qemu: SCSI id already used: %u\n", id); |
|
3937 |
return -1; |
|
3938 |
} |
|
3939 |
} |
|
3940 |
} else { |
|
3941 |
id = -1; |
|
3942 |
} |
|
3943 |
scsi_disks_info[i].adapter = temp_adapter; |
|
3944 |
scsi_disks_info[i].id = id; |
|
3945 |
|
|
3946 |
if (get_param_value(buf, sizeof(buf),"type",scsi_disk_options[i])) { |
|
3947 |
if (!strcmp(buf, "disk")) { |
|
3948 |
cdrom_device = 0; |
|
3949 |
} else if (!strcmp(buf, "cdrom")) { |
|
3950 |
cdrom_device = 1; |
|
3951 |
} else { |
|
3952 |
fprintf(stderr, "qemu: invalid SCSI disk type= value: %s\n", buf); |
|
3953 |
return -1; |
|
3954 |
} |
|
3955 |
} else { |
|
3956 |
cdrom_device = 0; |
|
3957 |
} |
|
3958 |
|
|
3959 |
if (cdrom_device) { |
|
3960 |
snprintf(dev_name, sizeof(buf), "cdrom%c", scsi_index); |
|
3961 |
scsi_disks_info[scsi_index].device_type = SCSI_CDROM; |
|
3962 |
} else { |
|
3963 |
snprintf(dev_name, sizeof(buf), "sd%c", scsi_index + 'a'); |
|
3964 |
scsi_disks_info[scsi_index].device_type = SCSI_DISK; |
|
3965 |
} |
|
3966 |
|
|
3967 |
if (!(bs_scsi_table[scsi_index] = bdrv_new(dev_name))) { |
|
3968 |
fprintf(stderr, "qemu: unable to create new block device for:%s\n",dev_name); |
|
3969 |
return -1; |
|
3970 |
} |
|
3971 |
|
|
3972 |
/* Get image filename from options and then try to open it */ |
|
3973 |
if (get_param_value(buf, sizeof(buf),"img",scsi_disk_options[i])) { |
|
3974 |
if (bdrv_open(bs_scsi_table[scsi_index], buf, 0) < 0) { |
|
3975 |
fprintf(stderr, "qemu: could not open SCSI disk image img='%s'\n",buf); |
|
3976 |
return -1; |
|
3977 |
} |
|
3978 |
} else { |
|
3979 |
fprintf(stderr, "qemu: SCSI disk image not specified for sd%c \n", i + 'a'); |
|
3980 |
return -1; |
|
3981 |
} |
|
3982 |
} |
|
3983 |
|
|
3984 |
return 0; |
|
3985 |
} |
|
3986 |
|
|
3987 |
|
|
3818 | 3988 |
/***********************************************************/ |
3819 | 3989 |
/* USB devices */ |
3820 | 3990 |
|
... | ... | |
5923 | 6093 |
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" |
5924 | 6094 |
"-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n" |
5925 | 6095 |
"-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n" |
6096 |
"-disk ide,img=file[,hdx=a..dd][,type=disk|cdrom] \n" |
|
6097 |
" defaults are: hdx=a,type=disk \n" |
|
6098 |
"-disk scsi,img=file[,sdx=a..g][,type=disk|cdrom][,id=n] \n" |
|
6099 |
" defaults are: sdx=a,type=disk,id='auto assign' \n" |
|
5926 | 6100 |
"-snapshot write to temporary files instead of disk image files\n" |
5927 | 6101 |
#ifdef CONFIG_SDL |
5928 | 6102 |
"-no-quit disable SDL window close capability\n" |
... | ... | |
6103 | 6277 |
QEMU_OPTION_no_acpi, |
6104 | 6278 |
QEMU_OPTION_no_reboot, |
6105 | 6279 |
QEMU_OPTION_daemonize, |
6280 |
QEMU_OPTION_disk, |
|
6106 | 6281 |
}; |
6107 | 6282 |
|
6108 | 6283 |
typedef struct QEMUOption { |
... | ... | |
6177 | 6352 |
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, |
6178 | 6353 |
{ "smp", HAS_ARG, QEMU_OPTION_smp }, |
6179 | 6354 |
{ "vnc", HAS_ARG, QEMU_OPTION_vnc }, |
6355 |
{ "disk", HAS_ARG, QEMU_OPTION_disk }, |
|
6180 | 6356 |
|
6181 | 6357 |
/* temporary options */ |
6182 | 6358 |
{ "usb", 0, QEMU_OPTION_usb }, |
... | ... | |
6395 | 6571 |
int i, cdrom_index; |
6396 | 6572 |
int snapshot, linux_boot; |
6397 | 6573 |
const char *initrd_filename; |
6398 |
const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; |
|
6574 |
const char *fd_filename[MAX_FD]; |
|
6575 |
char scsi_options[MAX_SCSI_DISKS] [DISK_OPTIONS_SIZE]; |
|
6576 |
char ide_options[MAX_DISKS] [DISK_OPTIONS_SIZE]; |
|
6577 |
int num_ide_disks; |
|
6578 |
int num_scsi_disks; |
|
6399 | 6579 |
const char *kernel_filename, *kernel_cmdline; |
6400 | 6580 |
DisplayState *ds = &display_state; |
6401 | 6581 |
int cyls, heads, secs, translation; |
... | ... | |
6450 | 6630 |
register_machines(); |
6451 | 6631 |
machine = first_machine; |
6452 | 6632 |
initrd_filename = NULL; |
6633 |
for(i = 0; i < MAX_SCSI_DISKS; i++) { |
|
6634 |
scsi_disks_info[i].device_type = SCSI_NONE; |
|
6635 |
bs_scsi_table[i] = NULL; |
|
6636 |
} |
|
6637 |
|
|
6638 |
num_ide_disks = 0; |
|
6639 |
num_scsi_disks = 0; |
|
6640 |
|
|
6453 | 6641 |
for(i = 0; i < MAX_FD; i++) |
6454 | 6642 |
fd_filename[i] = NULL; |
6455 |
for(i = 0; i < MAX_DISKS; i++) |
|
6456 |
hd_filename[i] = NULL; |
|
6643 |
for(i = 0; i < MAX_DISKS; i++) { |
|
6644 |
ide_options[i][0] = '\0'; |
|
6645 |
} |
|
6457 | 6646 |
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; |
6458 | 6647 |
vga_ram_size = VGA_RAM_SIZE; |
6459 | 6648 |
bios_size = BIOS_SIZE; |
... | ... | |
6497 | 6686 |
break; |
6498 | 6687 |
r = argv[optind]; |
6499 | 6688 |
if (r[0] != '-') { |
6500 |
hd_filename[0] = argv[optind++]; |
|
6689 |
|
|
6690 |
/* Build new disk IDE syntax string */ |
|
6691 |
pstrcpy(ide_options[0], |
|
6692 |
14, |
|
6693 |
"hdx=a,img="); |
|
6694 |
/*Add on image filename */ |
|
6695 |
pstrcpy(&(ide_options[0][13]), |
|
6696 |
sizeof(ide_options[0])-13, |
|
6697 |
argv[optind++]); |
|
6698 |
num_ide_disks++; |
|
6501 | 6699 |
} else { |
6502 | 6700 |
const QEMUOption *popt; |
6503 | 6701 |
|
... | ... | |
6547 | 6745 |
case QEMU_OPTION_hdd: |
6548 | 6746 |
{ |
6549 | 6747 |
int hd_index; |
6748 |
const char newIDE_DiskSyntax [][10] = { |
|
6749 |
"hdx=a,img=", "hdx=b,img=", "hdx=c,img=", "hdx=d,img=" }; |
|
6750 |
|
|
6550 | 6751 |
hd_index = popt->index - QEMU_OPTION_hda; |
6551 |
hd_filename[hd_index] = optarg; |
|
6552 |
if (hd_index == cdrom_index) |
|
6553 |
cdrom_index = -1; |
|
6752 |
if (num_ide_disks >= MAX_DISKS){ |
|
6753 |
fprintf(stderr, "qemu: too many IDE disks defined.\n"); |
|
6754 |
exit(1); |
|
6755 |
} |
|
6756 |
/* Build new disk IDE syntax string */ |
|
6757 |
pstrcpy(ide_options[hd_index], |
|
6758 |
11, |
|
6759 |
newIDE_DiskSyntax[hd_index]); |
|
6760 |
/* Add on image filename */ |
|
6761 |
pstrcpy(&(ide_options[hd_index][10]), |
|
6762 |
sizeof(ide_options[0])-10, |
|
6763 |
optarg); |
|
6764 |
num_ide_disks++; |
|
6765 |
} |
|
6766 |
break; |
|
6767 |
case QEMU_OPTION_disk: /*Combined IDE and SCSI, for disk and CDROM */ |
|
6768 |
{ |
|
6769 |
const char *p_input_char; |
|
6770 |
char *p_output_string; |
|
6771 |
char device[64]; |
|
6772 |
int disk_index; |
|
6773 |
|
|
6774 |
p_input_char = optarg; |
|
6775 |
p_output_string = device; |
|
6776 |
while (*p_input_char != '\0' && *p_input_char != ',') { |
|
6777 |
if ((p_output_string - device) < sizeof(device) - 1) |
|
6778 |
*p_output_string++ = *p_input_char; |
|
6779 |
p_input_char++; |
|
6780 |
} |
|
6781 |
*p_output_string = '\0'; |
|
6782 |
if (*p_input_char == ',') |
|
6783 |
p_input_char++; |
|
6784 |
|
|
6785 |
if (!strcmp(device, "scsi")) { |
|
6786 |
if (num_scsi_disks >= MAX_SCSI_DISKS) { |
|
6787 |
fprintf(stderr, "qemu: too many SCSI disks defined.\n"); |
|
6788 |
exit(1); |
|
6789 |
} |
|
6790 |
pstrcpy(scsi_options[num_scsi_disks], |
|
6791 |
sizeof(scsi_options[0]), |
|
6792 |
p_input_char); |
|
6793 |
num_scsi_disks++; |
|
6794 |
} else if (!strcmp(device,"ide")) { |
|
6795 |
if (num_ide_disks >= MAX_DISKS) { |
|
6796 |
fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n"); |
|
6797 |
exit(1); |
|
6798 |
} |
|
6799 |
disk_index = 0; /* default is hda */ |
|
6800 |
if (get_param_value(device, sizeof(device),"hdx",p_input_char)) { |
|
6801 |
if (device[0] >= 'a' && device[0] <= 'd') { |
|
6802 |
disk_index = device[0] - 'a'; |
|
6803 |
} else { |
|
6804 |
fprintf(stderr, "qemu: invalid IDE disk hdx= value: %s\n", device); |
|
6805 |
return -1; |
|
6806 |
} |
|
6807 |
} |
|
6808 |
else disk_index=0; |
|
6809 |
pstrcpy(ide_options[disk_index], |
|
6810 |
sizeof(ide_options[0]), |
|
6811 |
p_input_char); |
|
6812 |
num_ide_disks++; |
|
6813 |
} else { |
|
6814 |
fprintf(stderr, "qemu: -disk option must specify IDE or SCSI: %s \n",device); |
|
6815 |
exit(1); |
|
6816 |
} |
|
6554 | 6817 |
} |
6555 | 6818 |
break; |
6556 | 6819 |
case QEMU_OPTION_snapshot: |
... | ... | |
6604 | 6867 |
kernel_cmdline = optarg; |
6605 | 6868 |
break; |
6606 | 6869 |
case QEMU_OPTION_cdrom: |
6607 |
if (cdrom_index >= 0) { |
|
6608 |
hd_filename[cdrom_index] = optarg; |
|
6870 |
{ |
|
6871 |
char buf[24]; |
|
6872 |
if (num_ide_disks >= MAX_DISKS) { |
|
6873 |
fprintf(stderr, "qemu: too many IDE disks/cdroms defined.\n"); |
|
6874 |
exit(1); |
|
6875 |
} |
|
6876 |
snprintf(buf, sizeof(buf), "type=cdrom,hdx=%c,img=", cdrom_index + 'a'); |
|
6877 |
/* Build new disk IDE syntax string */ |
|
6878 |
pstrcpy(ide_options[cdrom_index], |
|
6879 |
25, |
|
6880 |
buf); |
|
6881 |
/* Add on image filename */ |
|
6882 |
pstrcpy(&(ide_options[cdrom_index][24]), |
|
6883 |
sizeof(ide_options[0])-24, |
|
6884 |
optarg); |
|
6885 |
num_ide_disks++; |
|
6609 | 6886 |
} |
6610 | 6887 |
break; |
6611 | 6888 |
case QEMU_OPTION_boot: |
... | ... | |
6893 | 7170 |
kqemu_allowed = 0; |
6894 | 7171 |
#endif |
6895 | 7172 |
linux_boot = (kernel_filename != NULL); |
6896 |
|
|
6897 |
if (!linux_boot && |
|
6898 |
hd_filename[0] == '\0' && |
|
6899 |
(cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') && |
|
7173 |
|
|
7174 |
if (!linux_boot && |
|
7175 |
num_ide_disks == 0 && |
|
6900 | 7176 |
fd_filename[0] == '\0') |
6901 | 7177 |
help(); |
6902 |
|
|
6903 |
/* boot to cd by default if no hard disk */ |
|
6904 |
if (hd_filename[0] == '\0' && boot_device == 'c') { |
|
6905 |
if (fd_filename[0] != '\0') |
|
6906 |
boot_device = 'a'; |
|
6907 |
else |
|
6908 |
boot_device = 'd'; |
|
6909 |
} |
|
6910 | 7178 |
|
6911 | 7179 |
setvbuf(stdout, NULL, _IOLBF, 0); |
6912 | 7180 |
|
... | ... | |
6942 | 7210 |
exit(1); |
6943 | 7211 |
} |
6944 | 7212 |
|
6945 |
/* we always create the cdrom drive, even if no disk is there */ |
|
6946 | 7213 |
bdrv_init(); |
6947 |
if (cdrom_index >= 0) { |
|
6948 |
bs_table[cdrom_index] = bdrv_new("cdrom"); |
|
6949 |
bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM); |
|
7214 |
|
|
7215 |
/* open the virtual block devices, disks or CDRoms */ |
|
7216 |
if (disk_options_init(num_ide_disks,ide_options,snapshot, |
|
7217 |
num_scsi_disks,scsi_options, |
|
7218 |
cdrom_index, |
|
7219 |
cyls, heads, secs, translation)){ |
|
7220 |
exit(1); |
|
6950 | 7221 |
} |
6951 | 7222 |
|
6952 |
/* open the virtual block devices */ |
|
6953 |
for(i = 0; i < MAX_DISKS; i++) { |
|
6954 |
if (hd_filename[i]) { |
|
6955 |
if (!bs_table[i]) { |
|
6956 |
char buf[64]; |
|
6957 |
snprintf(buf, sizeof(buf), "hd%c", i + 'a'); |
|
6958 |
bs_table[i] = bdrv_new(buf); |
|
6959 |
} |
|
6960 |
if (bdrv_open(bs_table[i], hd_filename[i], snapshot ? BDRV_O_SNAPSHOT : 0) < 0) { |
|
6961 |
fprintf(stderr, "qemu: could not open hard disk image '%s'\n", |
|
6962 |
hd_filename[i]); |
|
6963 |
exit(1); |
|
6964 |
} |
|
6965 |
if (i == 0 && cyls != 0) { |
|
6966 |
bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs); |
|
6967 |
bdrv_set_translation_hint(bs_table[i], translation); |
|
6968 |
} |
|
6969 |
} |
|
7223 |
/* boot to floppy or default cd if no hard disk */ |
|
7224 |
if (num_ide_disks == 0 && boot_device == 'c') { |
|
7225 |
if (fd_filename[0] != '\0') |
|
7226 |
boot_device = 'a'; |
|
7227 |
else |
|
7228 |
boot_device = 'd'; |
|
6970 | 7229 |
} |
6971 | 7230 |
|
6972 | 7231 |
/* we always create at least one floppy disk */ |
Also available in: Unified diff