[Pancutan-commits] r58 - in pancutan: defs tests/lib/Pancutan/Test
tincho-guest at alioth.debian.org
tincho-guest at alioth.debian.org
Mon Aug 13 22:31:22 UTC 2007
Author: tincho-guest
Date: 2007-08-13 22:31:22 +0000 (Mon, 13 Aug 2007)
New Revision: 58
Modified:
pancutan/defs/Booting.yaml
pancutan/tests/lib/Pancutan/Test/Booting.pm
pancutan/tests/lib/Pancutan/Test/Files.pm
Log:
- Booting: added mips and mipsel support
- Files: added caching of size of files
Modified: pancutan/defs/Booting.yaml
===================================================================
--- pancutan/defs/Booting.yaml 2007-08-13 13:47:50 UTC (rev 57)
+++ pancutan/defs/Booting.yaml 2007-08-13 22:31:22 UTC (rev 58)
@@ -26,14 +26,30 @@
non_decoupled_sub: detect_sparc_partition
desc: Searches for an Sparc Disklabel type partition table
depends: scan_files
+ detect_sgi_partition:
+ type: first_cd
+ non_decoupled_sub: detect_sgi_partition
+ desc: Searches for an SGI Disklabel type partition table
+ depends: scan_files
+ detect_pmax_partition:
+ type: first_cd
+ non_decoupled_sub: detect_pmax_partition
+ desc: Searches for an PMAX (DECStation/MIPSel) boot block
+ depends: scan_files
# desc: Scans the image for boot loaders (isolinux, yaboot, etc)
errors:
+ unknown-boot:
+ type: warn
+ desc: The bootable image cannot be mapped to a file
+ missing-boot-element:
+ type: error
+ desc: Some part of the boot process is missing
+ invalid-boot-element:
+ type: error
+ desc: Some part of the boot process is invalid
invalid-eltorito:
type: error
desc: El Torito specification found, but it's invalid or contains errors
- unknown-boot:
- type: warn
- desc: The bootable image cannot be mapped to a file
invalid-apm:
type: error
desc: APM partition table found, but it's invalid or contains errors
@@ -46,6 +62,6 @@
invalid-sunlabel:
type: error
desc: Sun Disklabel partition table found, but it's invalid or contains errors
- missing-boot-element:
+ invalid-sgilabel:
type: error
- desc: Some part of the boot process is missing
+ desc: SGI Disklabel partition table found, but it's invalid or contains errors
Modified: pancutan/tests/lib/Pancutan/Test/Booting.pm
===================================================================
--- pancutan/tests/lib/Pancutan/Test/Booting.pm 2007-08-13 13:47:50 UTC (rev 57)
+++ pancutan/tests/lib/Pancutan/Test/Booting.pm 2007-08-13 22:31:22 UTC (rev 58)
@@ -127,6 +127,26 @@
0x8e => "Linux LVM",
0xfd => "LInux RAID"
);
+my %sgitypes = ( # Taken from fdisk
+ 0x00 => "SGI volhdr",
+ 0x01 => "SGI trkrepl",
+ 0x02 => "SGI secrepl",
+ 0x03 => "SGI raw",
+ 0x04 => "SGI bsd",
+ 0x05 => "SGI sysv",
+ 0x06 => "SGI volume",
+ 0x07 => "SGI efs",
+ 0x08 => "SGI lvol",
+ 0x09 => "SGI rlvol",
+ 0x0a => "SGI xfs",
+ 0x0b => "SGI xfslog",
+ 0x0c => "SGI xlv",
+ 0x0d => "SGI xvm",
+ 0x82 => "Linux swap",
+ 0x83 => "Linux native",
+ 0x8e => "Linux LVM",
+ 0xfd => "Linux RAID"
+);
sub read_eltorito {
my ($meta, $ncd, $scratch) = @_;
@@ -249,7 +269,7 @@
my $file = $meta->{set}[$ncd]{file};
sysopen($fh, $file, O_RDONLY) or die "Error opening ISO file: $!";
my $buf = _myread($fh, 0, 1024);
- if(substr($buf, 0, 2) ne "ER") {
+ if(substr($buf, 0, 2) ne "ER") { # Magic
close($fh);
return ();
}
@@ -261,7 +281,7 @@
$buf = _myread($fh, 0, $bs * (1 + $nr));
my @partitions;
foreach(1..$nr) {
- if(substr($buf, $bs * $_, 2) ne "PM") {
+ if(substr($buf, $bs * $_, 2) ne "PM") { # Magic
push(@res, "invalid-apm", "Invalid signature in APM partition $_: "
. substr($buf, $bs * $_, 2));
next;
@@ -320,7 +340,7 @@
info("Mac bootfile: $_");
push(@{$meta->{set}[$ncd]{boot}{files}}, [ mac => $_ ]);
} else {
- push(@res, "unknown-boot", "Cannot find $_");
+ push(@res, "unknown-boot", "Cannot find bootfile $_");
}
}
close($fh);
@@ -332,7 +352,7 @@
my $fh;
sysopen($fh, $file, O_RDONLY) or die "Error opening ISO file: $!";
my $buf = _myread($fh, 0, 512);
- unless(substr($buf, 510, 2) eq "\x55\xaa") {
+ unless(substr($buf, 510, 2) eq "\x55\xaa") { # Magic
close($fh);
return ();
}
@@ -353,6 +373,7 @@
} else {
$pdesc = $mbrtypes{$type};
}
+ # Start is in 512-byte blocks
my $start = unpack("V", substr($buf, 0x1be + 16 * $_ + 8, 4));
my $size = unpack("V", substr($buf, 0x1be + 16 * $_ + 12, 4));
if($start % 4) {
@@ -380,8 +401,8 @@
push(@res, "invalid-mbr", "Partition type \"$pdesc\" points to ",
"beggining of ISO image, but I don't know how to handle it");
} elsif(not exists($scratch->{lsnidx}{$start})) {
- push(@res, "unknown-boot", "Partition " . ($_ + 1) .
- " points to block $start");
+ push(@res, "unknown-boot", "Cannot file the file that " .
+ "corresponds to LSN $start, pointed by partition ". ($_ + 1));
next;
}
my $bfile = $scratch->{lsnidx}{$start};
@@ -405,10 +426,10 @@
my($fh, $buf, @res);
sysopen($fh, $file, O_RDONLY) or die "Error opening ISO file: $!";
$buf = _myread($fh, 0, 512);
- unless(unpack("V", substr($buf, 0, 4)) == 0x82564557) {
+ unless(unpack("V", substr($buf, 0, 4)) == 0x82564557) { # Magic
$buf = _myread($fh, 512, 512);
}
- unless(unpack("V", substr($buf, 0, 4)) == 0x82564557) {
+ unless(unpack("V", substr($buf, 0, 4)) == 0x82564557) { # Can be in sector 1
close($fh);
return ();
}
@@ -422,7 +443,7 @@
my($fh, $buf, @res);
sysopen($fh, $file, O_RDONLY) or die "Error opening ISO file: $!";
$buf = _myread($fh, 0, 512);
- unless(unpack("n", substr($buf, 508, 2)) == 0xdabe) {
+ unless(unpack("n", substr($buf, 508, 2)) == 0xdabe) { # Magic
close($fh);
return ();
}
@@ -430,9 +451,9 @@
my $label = unpack("Z*", substr($buf, 0, 128));
my $volname = unpack("Z*", substr($buf, 132, 8));
my $nr = unpack("n", substr($buf, 140, 2));
- my $sane = unpack("N", substr($buf, 188, 4));
+ my $sane = unpack("N", substr($buf, 188, 4)); # Validation?
my $cylsize = (unpack("n", substr($buf, 436, 2)) *
- unpack("n", substr($buf, 438, 2)));
+ unpack("n", substr($buf, 438, 2))); # Size of cyls
my $chksum = 0;
$chksum ^= $_ foreach(unpack("n*", $buf));
if($chksum) {
@@ -443,10 +464,10 @@
}
my %bootstarts;
foreach(0..($nr - 1)) {
- my $tag = unpack("n", substr($buf, 142 + $_ * 4, 2));
- my $lag = unpack("n", substr($buf, 144 + $_ * 4, 2));
- my $start = unpack("N", substr($buf, 444 + $_ * 8, 4));
- my $size = unpack("N", substr($buf, 448 + $_ * 8, 4));
+ my $tag = unpack("n", substr($buf, 142 + $_ * 4, 2)); # part type
+ my $flag = unpack("n", substr($buf, 144 + $_ * 4, 2)); # RO, unmountable
+ my $start = unpack("N", substr($buf, 444 + $_ * 8, 4)); # start cyl
+ my $size = unpack("N", substr($buf, 448 + $_ * 8, 4)); # blocks
next unless($tag);
$bootstarts{$start} = 1; # eliminate duplicates, we only care about
# start location
@@ -476,6 +497,180 @@
close($fh);
return(@res);
}
+sub detect_sgi_partition {
+ my ($meta, $ncd, $scratch) = @_;
+ my $file = $meta->{set}[$ncd]{file};
+ my($fh, $buf, @res);
+ sysopen($fh, $file, O_RDONLY) or die "Error opening ISO file: $!";
+ $buf = _myread($fh, 0, 512);
+ unless(unpack("N", substr($buf, 0, 4)) == 0x0be5a941) { # Magic
+ close($fh);
+ return ();
+ }
+ info("SGI disklabel detected");
+ my $rootpt = unpack("n", substr($buf, 4, 2));
+ my $swappt = unpack("n", substr($buf, 6, 2));
+ my $bootfile = unpack("Z*", substr($buf, 8, 16));
+ my $chksum = unpack("%32N*", $buf);
+ if($chksum) {
+ push(@res, "invalid-sgilabel", "Invalid checksum: $chksum");
+ }
+ my @vhd;
+ foreach(0..14) {
+ my $vhfname = unpack("Z*", substr($buf, 72 + 16 * $_, 8));
+ my $vhfstart = unpack("N", substr($buf, 80 + 16 * $_, 4));
+ my $vhfsize = unpack("N", substr($buf, 84 + 16 * $_, 4));
+ next unless($vhfsize);
+ push @vhd, {
+ name => $vhfname,
+ start => $vhfstart,
+ size => $vhfsize
+ };
+ }
+ my @parts;
+ my $vhnr = 8;
+ foreach(0..15) {
+ my $partsize = unpack("N", substr($buf, 312 + 12 * $_, 4));
+ my $partstart = unpack("N", substr($buf, 316 + 12 * $_, 4));
+ my $parttype = unpack("N", substr($buf, 320 + 12 * $_, 4));
+ next unless($partsize);
+ $parts[$_] = {
+ type => $parttype,
+ start => $partstart,
+ size => $partsize
+ };
+ unless(exists $sgitypes{$parttype}) {
+ push(@res, "invalid-sgilabel", "Partition type $parttype unknown");
+ }
+ if($_ != 10 and $parttype == 3) {
+ push(@res, "invalid-sgilabel", "Raw partition in wrong position");
+ }
+ if($parttype == 3 and $partstart != 0) {
+ push(@res, "invalid-sgilabel", "Raw partition starts in ",
+ "sector $partstart");
+ }
+ if($_ != 8 and $parttype == 0) {
+ push(@res, "invalid-sgilabel", "Volume Header in wrong position");
+ $vhnr = $_;
+ }
+ info("SGI Partition: ", $_ + 1, ", type: $sgitypes{$parttype}, ",
+ "start: $partstart, size: $partsize");
+ }
+ if(! $parts[10]) {
+ push(@res, "invalid-sgilabel", "There's no raw partition defined");
+ }
+ if(! $parts[$vhnr]) {
+ push(@res, "invalid-sgilabel", "There's no volume header defined");
+ close($fh);
+ return(@res);
+ }
+ foreach(@vhd) {
+ my $lsn = ($parts[8]{start} + $_->{start}) / 4;
+ if(! exists($scratch->{lsnidx}{$lsn})) {
+ push(@res, "unknown-boot", "Cannot file the file that " .
+ "corresponds to LSN $lsn, named $_->{name} in the VHD");
+ } else {
+ my $bfile = $scratch->{lsnidx}{$lsn};
+ info("MIPS boot file: $bfile");
+ push(@{$meta->{set}[$ncd]{boot}{files}}, [ mips => $bfile ]);
+ }
+ }
+ close($fh);
+ return(@res);
+}
+sub detect_pmax_partition {
+ my ($meta, $ncd, $scratch) = @_;
+ my $file = $meta->{set}[$ncd]{file};
+ my($fh, $buf, @res);
+ sysopen($fh, $file, O_RDONLY) or die "Error opening ISO file: $!";
+ $buf = _myread($fh, 0, 512);
+ unless(unpack("V", substr($buf, 8, 4)) == 0x0002757a) { # Magic
+ close($fh);
+ return ();
+ }
+ info("PMAX (DECstation/MIPSel) boot block detected");
+ my $loadaddr = unpack("V", substr($buf, 16, 4));
+ my $execaddr = unpack("V", substr($buf, 20, 4));
+ my $size = unpack("V", substr($buf, 24, 4));
+ my $start = unpack("V", substr($buf, 28, 4)) / 4; # 512-byte blocks
+ my $realstart = $start;
+ if(! exists($scratch->{lsnidx}{$realstart})) {
+ # Biggest block less that start, as this should map into an elf file
+ my @firstfiles = grep({ $_ <= $start } sort({ $a <=> $b }
+ keys %{$scratch->{lsnidx}}));
+ $realstart = $firstfiles[-1];
+ }
+ if(! exists($scratch->{lsnidx}{$realstart})) {
+ push(@res, "unknown-boot", "Cannot file the file that " .
+ "corresponds to LSN $start, pointed from the boot block");
+ close($fh);
+ return(@res);
+ }
+ my $bfile = $scratch->{lsnidx}{$realstart};
+ my $realsize = $scratch->{files}{$bfile}{size};
+ $buf = _myread($fh, $realstart * 2048, $realsize);
+ close($fh);
+ if(index($buf, "etc/delo.conf") >= 0) {
+ info("DELO boot loader: $bfile");
+ if(! $scratch->{files}{"etc/delo.conf"}) {
+ push(@res, "missing-boot-element",
+ "Missing DELO configuration file");
+ } else {
+ push(@{$meta->{set}[$ncd]{boot}{files}}, [ delo => $bfile ]);
+ }
+ } else {
+ info("Unknown boot loader: $bfile");
+ push(@{$meta->{set}[$ncd]{boot}{files}}, [ mipsel => $bfile ]);
+ }
+ if($realstart == $start) {
+ # OK, so this should NOT be an ELF, but a raw binary
+ if(substr($buf, 0, 4) eq "\x7fELF") {
+ push(@res, "invalid-boot-element", "The boot block points to " .
+ "the beginning of an ELF file, which cannot be executed by ",
+ "MIPSel firmware");
+ }
+ return(@res);
+ }
+ # Parse ELF header -- this is neverending...
+ if(substr($buf, 0, 4) ne "\x7fELF") {
+ push(@res, "invalid-boot-element", "The boot block points inside a " .
+ "file I cannot understand (not ELF)");
+ return(@res);
+ }
+ unless(ord(substr($buf, 4, 1)) == 1 and # EI_CLASS == ELFCLASS32
+ ord(substr($buf, 5, 1)) == 1 and # EI_DATA == ELFDATA2LSB
+ ord(substr($buf, 6, 1)) == 1 and # EI_VERSION == EV_CURRENT
+ unpack("v", substr($buf, 16, 2)) == 2 and # ehdr.e_type == ET_EXEC
+ unpack("v", substr($buf, 18, 2)) == 8 and # ehdr.e_machine == EM_MIPS
+ unpack("V", substr($buf, 20, 4)) == 1) { # ehdr.e_version == EV_CURRENT
+ push(@res, "invalid-boot-element", "The boot file is not a MIPS " .
+ "ELF32 little endian file");
+ }
+ if(unpack("V", substr($buf, 24, 4)) != $execaddr) {
+ push(@res, "invalid-boot-element", "Exec address mismatch");
+ }
+ my $phoff = unpack("V", substr($buf, 28, 4));
+ my $phnum = unpack("v", substr($buf, 44, 2));
+ if($phnum == 0 or $phoff == 0) {
+ push(@res, "invalid-boot-element", "ELF file doesn't have program ".
+ "sections");
+ return(@res);
+ }
+ foreach(0..($phnum - 1)) {
+ my $p_offset = unpack("V", substr($buf, $phoff + $_ * 32 + 4, 4));
+ next unless(($start - $realstart) * 2048 == $p_offset);
+ if(unpack("V", substr($buf, $phoff + $_ * 32 + 8, 4)) != $loadaddr) {
+ push(@res, "invalid-boot-element", "Load address mismatch");
+ }
+ unless(unpack("V", substr($buf, $phoff + $_ * 32 + 24, 4)) & 1) {
+ push(@res, "invalid-boot-element", "ELF segment is not executable");
+ }
+ return(@res);
+ }
+ push(@res, "invalid-boot-element", "The boot block doesn't point to any " .
+ "program section");
+ return(@res);
+}
sub _myread {
my($fh, $pos, $bytes) = @_;
my $buf;
Modified: pancutan/tests/lib/Pancutan/Test/Files.pm
===================================================================
--- pancutan/tests/lib/Pancutan/Test/Files.pm 2007-08-13 13:47:50 UTC (rev 57)
+++ pancutan/tests/lib/Pancutan/Test/Files.pm 2007-08-13 22:31:22 UTC (rev 58)
@@ -14,26 +14,29 @@
sub scan_files_slave {
my($global, $ncd, $scratch) = @_;
my $cd = $global->{set}[$ncd];
- my $file = $global->{set}[$ncd]{file};
- my $iso = Device::Cdio::ISO9660::IFS->new(
- -source => $file) or die "Error opening ISO file: $!";
+ my $file = $cd->{file};
+ my $iso = Device::Cdio::ISO9660::IFS->new(
+ -source => $file) or die "Error opening ISO file: $!";
my $basedir = canonpath($cd->{mount});
my @files;
find({ wanted => sub {
push @files, abs2rel($_, $basedir) if(-f);
}, no_chdir => 1}, $basedir);
- my @lsns = map {
+ my @stats = map {
my $s = $iso->stat($_);
defined($s) or die "Can't stat file $_";
- $s->{LSN} } @files;
+ ($s->{LSN}, $s->{size}) } @files;
$iso->close();
- return \@files, \@lsns;
+ return \@files, \@stats;
}
sub scan_files_master {
- my($global, $ncd, $scratch, $files, $lsns) = @_;
+ my($global, $ncd, $scratch, $files, $stats) = @_;
foreach(0..$#{$files}) {
- $scratch->{files}{$files->[$_]} = { LSN => $lsns->[$_] };
- $scratch->{lsnidx}{$lsns->[$_]} = $files->[$_];
+ $scratch->{files}{$files->[$_]} = {
+ LSN => $stats->[$_*2],
+ size => $stats->[$_*2+1],
+ };
+ $scratch->{lsnidx}{$stats->[$_*2]} = $files->[$_];
}
$scratch->{filelist} = [ @$files ];
debug(scalar @$files, " files found");
More information about the Pancutan-commits
mailing list