#!/usr/bin/perl -w
+use Data::Dumper;
print <<END
;
$pdir = $ENV{PALACIOS_DIR};
+$qdir = $ENV{PALACIOS_QEMU_DIR};
+
+$haveqemu = defined($qdir);
if (!defined($pdir)) {
print "Please set PALACIOS_DIR (you probably have not sourced ENV) and try again\n";
}
-$name = "guest";
+$name = "myguest";
print "What is the name of your guest? [$name] : ";
$name = get_user($name);
}
}
+do_swapping(\%config, $pdir);
+
print "We will give your guest the default performance tuning characteristics\n";
$config{perftune_block} .= <<PERFTUNE
$config{extensions_block} .= " <extension name=\"VMWARE_IFACE\"></extension>\n";
}
+
+do_bioses(\%config, $pdir, $dir);
+
+
#
# Basic debugging
#
#
do_device(\%config, $pdir, "V3_CONFIG_PIT", "8254_PIT", "PIT",1); # must have
-#
-# Keyboard and mouse (PS/2 controller)
-#
-do_device(\%config, $pdir, "V3_CONFIG_KEYBOARD", "KEYBOARD", "keyboard",1); #must have
+if (defined($ENV{PALACIOS_QEMU_DIR})) {
+ print "\nYour Palacios configuration includes the ability to use QEMU devices from a patched QEMU.\n";
+ print "Do you want to use QEMU's PS/2, graphics, and serial port devices? [n] : ";
+ if (get_user("n") eq "y") {
+ do_qemu_ui(\%config, $pdir, $dir);
+ }
+}
-#
-# Displays, Consoles, Serial
-#
-print "\nWe will now consider consoles and serial ports.\n\n";
-do_consoles_and_ports(\%config, $pdir);
+if (!defined($config{qemu_ui})) {
+ #
+ # Keyboard and mouse (PS/2 controller)
+ #
+ do_device(\%config, $pdir, "V3_CONFIG_KEYBOARD", "KEYBOARD", "keyboard",1); #must have
+
+ #
+ # Displays, Consoles, Serial
+ #
+ print "\nWe will now consider consoles and serial ports.\n\n";
+ do_consoles_and_ports(\%config, $pdir);
+
+}
#
do_storage(\%config, $pdir, $dir, $name, "pci0", "southbridge");
-#
-# NVRAM
-#
-# Note: do_storage *must* have placed an IDE named ide0 in order for this to work
-#
-do_device(\%config, $pdir, "V3_CONFIG_NVRAM", "NVRAM", "nvram", 1, undef, " <storage>ide0</storage>\n"); #must have
#
#
+# Sanity-check - is there something bootable?
+#
+#
+if (!($config{havecd} && !($config{havehd}))) {
+ print "The guest's storage configuration does not have either a CD or an HD. \n";
+ print "This means the guest BIOS will have nothing local to boot. \n";
+ if (!($config{havenic})) {
+ print "The guest also does does not have a NIC, which means the BIOS cannot\n";
+ print "do a network boot.\n";
+ } else {
+ print "The guest does have a NIC, so a network boot is possible, if the\n";
+ print "BIOS supports it.\n";
+ }
+ print "If this is not your intent, you probably want to CTRL-C and try again.\n";
+}
+
+print "The BIOS boot sequence will be set to CD,HD. If you need to change this\n";
+print "later, edit the <bootseq> block within the NVRAM device.\n";
+
+#
+# NVRAM
+#
+# Note: do_storage *must* have placed an IDE named ide0 in order for this to work
+#
+do_device(\%config, $pdir, "V3_CONFIG_NVRAM", "NVRAM", "nvram", 1, undef, " <storage>ide0</storage>\n <bootseq>cd,hd</bootseq>\n"); #must have
+
+#
#
# Generic Catch-all Device
#
print $target "<vm class=\"PC\">\n\n";
print $target file_setup(\%config), "\n";
+print $target bios_setup(\%config),"\n";
print $target memory_setup(\%config), "\n";
+print $target swapping_setup(\%config), "\n";
print $target paging_setup(\%config), "\n";
print $target memmap_setup(\%config), "\n";
print $target numa_setup(\%config), "\n";
close(PAL);
+#print Dumper(\%config);
+
+if (defined($config{qemu}) && $config{qemu} eq "y") {
+ gen_qemu_startup(\%config, $pdir, $dir);
+}
+
print "\n\nYour guest is now ready in the directory $dir\n\n";
print "To run it, do:\n\n";
print " cd $dir\n";
print " v3_create -b $name.pal $name\n";
-print " v3_launch /dev/v3-vmN (N given by v3_create\n\n";
+print " v3_launch /dev/v3-vmN (N given by v3_create)\n\n";
print "Other useful tools:\n\n";
print " v3_console (CGA console)\n";
print " v3_stream (connect to stream, for example, serial port)\n\n";
return %numa;
}
+
+sub do_swapping {
+ my ($cr, $pdir) = @_;
+
+ my $canswap = is_palacios_core_feature_enabled($pdir,"V3_CONFIG_SWAPPING");
+ my $mem = $cr->{mem};
+
+ if ($canswap) {
+ #Config for swapping
+ $cr->{swapping} = yn_question("Do you want to use swapping?", "n", "y", "n");
+
+ if ($cr->{swapping} eq "y") {
+ $cr->{swap_alloc} = quant_question("How much memory do you want to allocate [MB] ?", $mem/2);
+ print "We will use the default swapping strategy.\n";
+ $cr->{swap_strat} = "default";
+ print "What file do you want to swap to? [./swap.bin] ";
+ $cr->{swap_file} = get_user("./swap.bin");
+ }
+ }
+}
+
+sub add_bios {
+ my ($cr, $name, $fileid, $address) =@_;
+
+ push @{$cr->{bios_list}}, { name=>$name, fileid=>$fileid, address=>$address };
+
+}
+
+sub do_bios {
+ my ($cr, $pdir, $dir) = @_;
+ my $nextbios = defined($cr->{bios_list}) ? "bios".($#{$cr->{bios_list}}+1) : "bios0";
+
+ if (yn_question("Add a".($nextbios eq "bios0" ? "" : "nother")." custom bios? ", "n", "y", "n") eq "y") {
+ my ($n, $fn, $addr) ;
+ print "What is your name for this bios? [$nextbios] : ";
+ $n = get_user($nextbios);
+ while (1) {
+ print "Where is the path to the file for bios $n ? ";
+ $fn = get_user("");
+ if (!(-e $fn)) {
+ print "Cannot find $fn, try again\n";
+ next;
+ } else {
+ if (system("cp $fn $dir/$n.dat")) {
+ print "Unable to copy $fn\n";
+ next;
+ } else {
+ add_file($cr, "$n", "$n.dat");
+ print "What is the destination physical linear address (in hex) for bios $n [0xf0000] ? ";
+ $addr = get_user("0xf0000");
+ add_bios($cr,$n,$n,$addr);
+ return 1;
+ }
+ }
+ }
+ } else {
+ return 0;
+ }
+}
+
+sub do_bioses {
+ my ($cr, $pdir, $dir) = @_;
+
+ $cr->{bios_custom} = yn_question("Do you want to customize BIOSes? (done automatically later for QEMU devices) ", "n", "y", "n");
+
+ if ($cr->{bios_custom} eq "y") {
+ $cr->{bios_custom_nobios} = yn_question("Disable built-in system bios? ", "n", "y", "n");
+ $cr->{bios_custom_novgabios} = yn_question("Disable built-in VGA bios? ", "n", "y", "n");
+
+ while (do_bios($cr, $pdir, $dir)) {}
+ }
+}
+
+
+
+
sub do_device {
my ($cr,$pdir,$feature, $class, $id, $hardfail, $optblob, $nestblob) =@_;
}
}
+sub add_qemu_device {
+ my ($cr, $pdir, $type, $name, $url) = @_;
+
+ $cr->{qemu}='y';
+
+ push @{$cr->{qemu_devices}}, { type=>$type, name=>$name, url=>$url } ;
+
+}
+
+sub do_qemu_ui {
+ my ($cr, $pdir, $dir) = @_;
+ my $vgabios=$ENV{PALACIOS_QEMU_DIR}."/share/qemu/vgabios-cirrus.bin";
+
+ $cr->{qemu_ui}='y';
+
+ # PS/2 is a generic device
+ add_device($cr,"GENERIC","qemu-ps2",
+ " forward=\"host_device\" hostdev=\"user:qemu-ps2\" ",
+ " <ports> <start>0x60</start> <end>0x60</end> <mode>PASSTHROUGH</mode> </ports>\n".
+ " <ports> <start>0x64</start> <end>0x64</end> <mode>PASSTHROUGH</mode> </ports>\n".
+ " <ports> <start>0x80</start> <end>0x80</end> <mode>PASSTHROUGH</mode> </ports>\n");
+ add_qemu_device($cr,$pdir, "qemu-ps2", "qemu-ps2", "user:qemu-ps2");
+
+ # so is serial
+ add_device($cr,"GENERIC", "qemu-serial",
+ " forward=\"host_device\" hostdev=\"user:qemu-serial\" ",
+ " <ports> <start>0x3f8</start> <end>0x3ff</end> <mode>PASSTHROUGH</mode> </ports>\n".
+ " <ports> <start>0x2f8</start> <end>0x2ff</end> <mode>PASSTHROUGH</mode> </ports>\n".
+ " <ports> <start>0x3e8</start> <end>0x3ef</end> <mode>PASSTHROUGH</mode> </ports>\n".
+ " <ports> <start>0x2e8</start> <end>0x2ef</end> <mode>PASSTHROUGH</mode> </ports>\n");
+ add_qemu_device($cr,$pdir, "qemu-serial", "qemu-serial", "user:qemu-serial");
+
+ # Video has both a generic device and a PCI device (enhanced vga) and a bios
+ add_device($cr,"GENERIC", "qemu-video-legacy",
+ " forward=\"host_device\" hostdev=\"user:qemu-video-legacy\" ",
+ " <ports> <start>0x3b4</start> <end>0x3da</end> <mode>PASSTHROUGH</mode> </ports>\n".
+ " <memory> <start>0xa0000</start> <end>0xbffff</end> <mode>PASSTHROUGH</mode> </memory>\n");
+ add_qemu_device($cr,$pdir, "qemu-video-legacy", "qemu-video-legacy", "user:qemu-video-legacy");
+
+ add_device($cr, "PCI_FRONT", "qemu-video",
+ " hostdev=\"user:qemu-video\" ",
+ " <bus>pci0</bus>\n");
+
+ add_qemu_device($cr,$pdir, "qemu-video", "qemu-video", "user:qemu-video");
+
+ print "To use QEMU video, we will need to add the relevant bios. \n";
+ while (1) {
+ print "Where is the QEMU video bios ? [$vgabios] : ";
+ $vgabios = get_user($vgabios);
+ if (-e $vgabios) {
+ if (system("cp $vgabios $dir/qemu-videobios.dat")) {
+ print "Cannot copy $vgabios, try again\n";
+ next;
+ } else {
+ last;
+ }
+ } else {
+ print "Cannot find $vgabios, try again\n";
+ next;
+ }
+ }
+ add_file($cr, "qemu-videobios", "qemu-videobios.dat");
+ add_bios($cr, "qemu-videobios", "qemu-videobios", "0xc0000");
+ $cr->{bios_custom} = 'y';
+ $cr->{bios_custom_novgabios} = 'y';
+
+}
+
sub do_consoles_and_ports {
my ($cr, $pdir) = @_;
if (!($cancga || $canvga || $canserial || $canvirtioconsole)) {
print "Hmm... No console mechanism is enabled in your Palacios build...\n";
print " This is probably not what you want...\n";
-}
+ }
$didcga=0;
if ($cancga) {
print "You have configured your guest without any obvious way of interacting with it....\n";
print " This is probably not what you want...\n";
}
+
}
}
$num++;
}
+
+ if ($num>0) {
+ $cr->{havenic}=1;
+ }
}
do_storage_backend($cr, $pdir, $dir, $name, "virtioblk$i", "data$i", "");
}
}
-}
+
+}
+
sub do_storage_backend {
my ($cr, $pdir, $dir, $name, $frontend, $loc, $frontendblock) = @_;
- my ($canramdisk, $canfiledisk, $cannetdisk, $cantmpdisk);
+ my ($canramdisk, $canfiledisk, $cannetdisk, $cantmpdisk, $canqcowdisk);
my @devs=("cd","hd","nothing");
my @disks;
my $type;
$canramdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_RAMDISK");
$canfiledisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_FILEDISK");
+ $canqcowdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_QCOWDISK");
$cannetdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_NETDISK");
$cantmpdisk = is_palacios_core_feature_enabled($pdir, "V3_CONFIG_TMPDISK");
push @disks, "ramdisk" if $canramdisk;
push @disks, "filedisk" if $canramdisk;
+ push @disks, "qcowdisk" if $canramdisk;
push @disks, "netdisk" if $cannetdisk;
push @disks, "tmpdisk" if $cantmpdisk;
- if (!$canramdisk && !$canfiledisk && !$cannetdisk && !$cantmpdisk) {
+ if (!$canramdisk && !$canfiledisk && !$cannetdisk && !$cantmpdisk && !$canqcowdisk) {
print "You have no storage implementations enabled in your Palacios build, so it is impossible\n";
print "to add anything to storage controller \"$frontend\" location \"$loc\"\n";
return -1;
print "A storage device requires one of the following implementations\n";
print " * RAMDISK - the data is kept in memory (common) : ".($canramdisk ? "available" : "UNAVAILABLE")."\n";
print " * FILEDISK - the data is kept in a host file (common) : ".($canfiledisk ? "available" : "UNAVAILABLE")."\n";
+ print " * QCOWDISK - the data is kept in a host file (qcow) : ".($canqcowdisk ? "available" : "UNAVAILABLE")."\n";
print " * NETDISK - the data is accessed via the network (uncommon) : ".($cannetdisk ? "available" : "UNAVAILABLE")."\n";
print " * TMPDISK - the data is kept in memory and discarded (common) : ".($cantmpdisk ? "available" : "UNAVAILABLE")."\n";
while (1) {
last if $#test==0;
}
- if ($type eq "filedisk" || $type eq "ramdisk") {
+ if ($type eq "filedisk" || $type eq "ramdisk" || $type eq "qcowdisk") {
print "$type requires a file (.iso for example). Do you have one? [y] : ";
if (get_user("y") eq "y") {
while (1) {
if ($what eq "cd") {
$attach.=" <model>V3VEE CDROM</model>\n".
" <type>CDROM</type>\n".$frontendblock;
+ $cr->{havecd}=1;
} else {
$attach.=" <model>V3VEE HD</model>\n".
" <type>HD</type>\n".$frontendblock;
+ $cr->{havehd}=1;
}
$attach.=" </frontend>\n";
add_device($cr,"RAMDISK","$frontend\_$loc", undef,
" <file>$frontend\_$loc</file>\n".$attach);
add_file($cr, "$frontend\_$loc", "$frontend\_$loc.dat");
- } else {
+ } elsif ($type eq "filedisk") {
add_device($cr,"FILEDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef,
" <path>$frontend\_$loc.dat</path>\n".$attach);
+ } else {
+ add_device($cr,"QCOWDISK","$frontend\_$loc", $what eq "hd" ? "writable=\"1\"" : undef,
+ " <path>$frontend\_$loc.dat</path>\n".$attach);
}
last;
} else {
;
}
my @par = find_devices_by_class($cr,"SERIAL");
- if ($#par<0) {
+ if ($#par<0 && !defined($cr->{qemu_ui})) {
$block .=<<GENERIC3
<ports>
<!-- Serial COM 1 -->
return $s;
}
+sub swapping_setup {
+ my $cr=shift;
+ if (defined($cr->{swapping}) && $cr->{swapping} eq "y") {
+ return " <swapping enable=\"y\">\n <allocated>".$cr->{swap_alloc}."</allocated>\n <file>".$cr->{swap_file}."</file>\n <strategy>".$cr->{swap_strat}."</strategy>\n </swapping>\n";
+ } else {
+ return " <!-- there is no swapping configuration, but you can add one manually -->\n";
+ }
+}
sub telemetry_setup {
my $cr=shift;
return " <telemetry>".$cr->{telemetry}."</telemetry>\n";
}
}
+sub bios_setup {
+ my $cr=shift;
+
+ if (!defined($cr->{bios_custom}) || $cr->{bios_custom} eq "n") {
+ return " <!-- this configuration does not use a custom bios setup but you can add one with the <bioses> syntax-->\n";
+ } else {
+ my $s;
+ my $b;
+ $s = " <bioses>\n";
+ $s.= " <disable_rombios/>\n" if defined($cr->{bios_custom_nobios}) && $cr->{bios_custom_nobios} eq "y";
+ $s.= " <disable_vgabios/>\n" if defined($cr->{bios_custom_novgabios}) && $cr->{bios_custom_novgabios} eq "y";
+ foreach $b (@{$cr->{bios_list}}) {
+ $s.= " <bios file=\"".$b->{fileid}."\" address=\"".$b->{address}."\" />\n";
+ }
+ $s.= " </bioses>\n";
+ return $s;
+ }
+}
+
sub device_setup {
my $cr=shift;
my $cd;
return 0;
}
}
+
+
+sub gen_qemu_startup {
+ my ($cr, $pdir, $dir) = @_;
+ my $d;
+
+ # FIX ME
+ print "Generating QEMU Startup Script\n";
+
+ open(Q,">$dir/qemu_startup.sh");
+ print Q $ENV{PALACIOS_QEMU_DIR}."/bin/qemu-system-x86_64 -m 2048 -accel pal ";
+ foreach $d (@{$cr->{qemu_devices}}) {
+ if ($d->{type} eq "qemu-ps2") {
+ print Q " -map KBD ".$d->{url}." ";
+ } elsif ($d->{type} eq "qemu-serial") {
+ print Q " -serial stdio -map SERIAL ".$d->{url}." ";
+ } elsif ($d->{type} eq "qemu-video-legacy") {
+ print Q " -map VGA ".$d->{url}." ";
+ } elsif ($d->{type} eq "qemu-video") {
+ print Q " -vga cirrus -map CIRRUS ".$d->{url}." ";
+ } elsif ($d->{type} eq "qemu-e1000") {
+ print Q " -nic e1000 -map E1000 ".$d->{url}." ";
+ } elsif ($d->{type} eq "qemu-ide-legacy") {
+ print Q " -ide ... -map IDE-LEGACY ".$d->{url}." ";
+ } elsif ($d->{type} eq "qemu-ide") {
+ print Q " -ide ... -map IDE ".$d->{url}." ";
+ } else {
+ die "Do not know how to handle QEMU device of type ".$d->{type}."\n";
+ }
+ }
+
+ print Q "\n";
+
+ close(Q);
+}