#! /usr/bin/perl use strict; use warnings; use POSIX; use Getopt::Long qw(:config bundling); use Fcntl 'SEEK_SET'; # Read Pintos.pm from the same directory as this program. BEGIN { my $self = $0; $self =~ s%/+[^/]*$%%; require "$self/Pintos.pm"; } our ($disk_fn); # Output disk file name. our (%parts); # Partitions. our ($format); # "partitioned" (default) or "raw" our (%geometry); # IDE disk geometry. our ($align); # Align partitions on cylinders? our ($loader_fn); # File name of loader. our ($include_loader); # Include loader? our (@kernel_args); # Kernel arguments. if (grep ($_ eq '--', @ARGV)) { @kernel_args = @ARGV; @ARGV = (); while ((my $arg = shift (@kernel_args)) ne '--') { push (@ARGV, $arg); } } GetOptions ("h|help" => sub { usage (0); }, "kernel=s" => \&set_part, "filesys=s" => \&set_part, "scratch=s" => \&set_part, "swap=s" => \&set_part, "filesys-size=s" => \&set_part, "scratch-size=s" => \&set_part, "swap-size=s" => \&set_part, "kernel-from=s" => \&set_part, "filesys-from=s" => \&set_part, "scratch-from=s" => \&set_part, "swap-from=s" => \&set_part, "format=s" => \$format, "loader:s" => \&set_loader, "no-loader" => \&set_no_loader, "geometry=s" => \&set_geometry, "align=s" => \&set_align) or exit 1; usage (1) if @ARGV != 1; $disk_fn = $ARGV[0]; die "$disk_fn: already exists\n" if -e $disk_fn; # Sets the loader to copy to the MBR. sub set_loader { die "can't specify both --loader and --no-loader\n" if defined ($include_loader) && !$include_loader; $include_loader = 1; $loader_fn = $_[1] if $_[1] ne ''; } # Disables copying a loader to the MBR. sub set_no_loader { die "can't specify both --loader and --no-loader\n" if defined ($include_loader) && $include_loader; $include_loader = 0; } # Figure out whether to include a loader. $include_loader = exists ($parts{KERNEL}) && $format eq 'partitioned' if !defined ($include_loader); die "can't write loader to raw disk\n" if $include_loader && $format eq 'raw'; die "can't write command-line arguments without --loader or --kernel\n" if @kernel_args && !$include_loader; print STDERR "warning: --loader only makes sense without --kernel " . "if this disk will be used to load a kernel from another disk\n" if $include_loader && !exists ($parts{KERNEL}); # Open disk. my ($disk_handle); open ($disk_handle, '>', $disk_fn) or die "$disk_fn: create: $!\n"; # Read loader. my ($loader); $loader = read_loader ($loader_fn) if $include_loader; # Write disk. my (%disk) = %parts; $disk{DISK} = $disk_fn; $disk{HANDLE} = $disk_handle; $disk{ALIGN} = $align; $disk{GEOMETRY} = %geometry; $disk{FORMAT} = $format; $disk{LOADER} = $loader; $disk{ARGS} = \@kernel_args; assemble_disk (%disk); # Done. exit 0; sub usage { print <<'EOF'; pintos-mkdisk, a utility for creating Pintos virtual disks Usage: pintos-mkdisk [OPTIONS] DISK [-- ARGUMENT...] where DISK is the virtual disk to create, each ARGUMENT is inserted into the command line written to DISK, and each OPTION is one of the following options. Partition options: (where PARTITION is one of: kernel filesys scratch swap) --PARTITION=FILE Use a copy of FILE for the given PARTITION --PARTITION-size=SIZE Create an empty PARTITION of the given SIZE in MB --PARTITION-from=DISK Use of a copy of the given PARTITION in DISK (There is no --kernel-size option.) Output disk options: --format=partitioned Write partition table to output (default) --format=raw Do not write partition table to output (Pintos can only use partitioned disks.) Partitioned format output options: --loader[=FILE] Get bootstrap loader from FILE (default: loader.bin if --kernel option is specified, empty otherwise) --no-loader Do not include a bootstrap loader --geometry=H,S Use H head, S sector geometry (default: 16, 63) --geometry=zip Use 64 head, 32 sector geometry for USB-ZIP boot per http://syslinux.zytor.com/usbkey.php --align=bochs Round size to cylinder for Bochs support (default) --align=full Align partition boundaries to cylinder boundary to let fdisk guess correct geometry and quiet warnings --align=none Don't align partitions at all, to save space Other options: -h, --help Display this help message. EOF exit ($_[0]); }