Implement a proper block layer with partition support.
[pintos-anon] / src / utils / pintos-mkdisk
1 #! /usr/bin/perl
2
3 use strict;
4 use warnings;
5 use POSIX;
6 use Getopt::Long qw(:config bundling);
7 use Fcntl 'SEEK_SET';
8
9 # Read Pintos.pm from the same directory as this program.
10 BEGIN { my $self = $0; $self =~ s%/+[^/]*$%%; require "$self/Pintos.pm"; }
11
12 our ($disk_fn);                 # Output disk file name.
13 our (%parts);                   # Partitions.
14 our ($format);                  # "partitioned" (default) or "raw"
15 our (%geometry);                # IDE disk geometry.
16 our ($align);                   # Align partitions on cylinders?
17 our ($loader_fn);               # File name of loader.
18 our ($include_loader);          # Include loader?
19 our (@kernel_args);             # Kernel arguments.
20
21 if (grep ($_ eq '--', @ARGV)) {
22     @kernel_args = @ARGV;
23     @ARGV = ();
24     while ((my $arg = shift (@kernel_args)) ne '--') {
25         push (@ARGV, $arg);
26     }
27 }
28
29 GetOptions ("h|help" => sub { usage (0); },
30
31             "kernel=s" => \&set_part,
32             "filesys=s" => \&set_part,
33             "scratch=s" => \&set_part,
34             "swap=s" => \&set_part,
35
36             "filesys-size=s" => \&set_part,
37             "scratch-size=s" => \&set_part,
38             "swap-size=s" => \&set_part,
39
40             "kernel-from=s" => \&set_part,
41             "filesys-from=s" => \&set_part,
42             "scratch-from=s" => \&set_part,
43             "swap-from=s" => \&set_part,
44
45             "format=s" => \$format,
46             "loader:s" => \&set_loader,
47             "no-loader" => \&set_no_loader,
48             "geometry=s" => \&set_geometry,
49             "align=s" => \&set_align)
50   or exit 1;
51 usage (1) if @ARGV != 1;
52
53 $disk_fn = $ARGV[0];
54 die "$disk_fn: already exists\n" if -e $disk_fn;
55
56 # Sets the loader to copy to the MBR.
57 sub set_loader {
58     die "can't specify both --loader and --no-loader\n"
59       if defined ($include_loader) && !$include_loader;
60     $include_loader = 1;
61     $loader_fn = $_[1] if $_[1] ne '';
62 }
63
64 # Disables copying a loader to the MBR.
65 sub set_no_loader {
66     die "can't specify both --loader and --no-loader\n"
67       if defined ($include_loader) && $include_loader;
68     $include_loader = 0;
69 }
70
71 # Figure out whether to include a loader.
72 $include_loader = exists ($parts{KERNEL}) && $format eq 'partitioned'
73   if !defined ($include_loader);
74 die "can't write loader to raw disk\n" if $include_loader && $format eq 'raw';
75 die "can't write command-line arguments without --loader or --kernel\n"
76   if @kernel_args && !$include_loader;
77 print STDERR "warning: --loader only makes sense without --kernel "
78   . "if this disk will be used to load a kernel from another disk\n"
79   if $include_loader && !exists ($parts{KERNEL});
80
81 # Open disk.
82 my ($disk_handle);
83 open ($disk_handle, '>', $disk_fn) or die "$disk_fn: create: $!\n";
84
85 # Read loader.
86 my ($loader);
87 $loader = read_loader ($loader_fn) if $include_loader;
88
89 # Write disk.
90 my (%disk) = %parts;
91 $disk{DISK} = $disk_fn;
92 $disk{HANDLE} = $disk_handle;
93 $disk{ALIGN} = $align;
94 $disk{GEOMETRY} = %geometry;
95 $disk{FORMAT} = $format;
96 $disk{LOADER} = $loader;
97 $disk{ARGS} = \@kernel_args;
98 assemble_disk (%disk);
99
100 # Done.
101 exit 0;
102
103 sub usage {
104     print <<'EOF';
105 pintos-mkdisk, a utility for creating Pintos virtual disks
106 Usage: pintos-mkdisk [OPTIONS] DISK [-- ARGUMENT...]
107 where DISK is the virtual disk to create,
108       each ARGUMENT is inserted into the command line written to DISK,
109   and each OPTION is one of the following options.
110 Partition options: (where PARTITION is one of: kernel filesys scratch swap)
111   --PARTITION=FILE         Use a copy of FILE for the given PARTITION
112   --PARTITION-size=SIZE    Create an empty PARTITION of the given SIZE in MB
113   --PARTITION-from=DISK    Use of a copy of the given PARTITION in DISK
114   (There is no --kernel-size option.)
115 Output disk options:
116   --format=partitioned     Write partition table to output (default)
117   --format=raw             Do not write partition table to output
118   (Pintos can only use partitioned disks.)
119 Partitioned format output options:
120   --loader[=FILE]          Get bootstrap loader from FILE (default: loader.bin
121                            if --kernel option is specified, empty otherwise)
122   --no-loader              Do not include a bootstrap loader
123   --geometry=H,S           Use H head, S sector geometry (default: 16, 63)
124   --geometry=zip           Use 64 head, 32 sector geometry for USB-ZIP boot
125                            per http://syslinux.zytor.com/usbkey.php
126   --align=bochs            Round size to cylinder for Bochs support (default)
127   --align=full             Align partition boundaries to cylinder boundary to
128                            let fdisk guess correct geometry and quiet warnings
129   --align=none             Don't align partitions at all, to save space
130 Other options:
131   -h, --help               Display this help message.
132 EOF
133     exit ($_[0]);
134 }