[Pancutan-commits] r57 - in pancutan: defs tests/lib/Pancutan/Test

tincho-guest at alioth.debian.org tincho-guest at alioth.debian.org
Mon Aug 13 13:47:50 UTC 2007


Author: tincho-guest
Date: 2007-08-13 13:47:50 +0000 (Mon, 13 Aug 2007)
New Revision: 57

Modified:
   pancutan/defs/Booting.yaml
   pancutan/tests/lib/Pancutan/Test/Booting.pm
   pancutan/tests/lib/Pancutan/Test/Files.pm
Log:
Finish APM partitions, added MBR, SUN & BSD detection


Modified: pancutan/defs/Booting.yaml
===================================================================
--- pancutan/defs/Booting.yaml	2007-08-13 07:15:06 UTC (rev 56)
+++ pancutan/defs/Booting.yaml	2007-08-13 13:47:50 UTC (rev 57)
@@ -11,10 +11,21 @@
     type: first_cd
     non_decoupled_sub: detect_apm_partition
     desc: Searches for an Apple Partition Map type partition table
+    depends: scan_files
   detect_mbr_partition:
     type: first_cd
     non_decoupled_sub: detect_mbr_partition
     desc: Searches for an Master Boot Record type partition table
+    depends: scan_files
+  detect_bsd_partition:
+    type: first_cd
+    non_decoupled_sub: detect_bsd_partition
+    desc: Searches for an BSD Disklabel type partition table
+  detect_sparc_partition:
+    type: first_cd
+    non_decoupled_sub: detect_sparc_partition
+    desc: Searches for an Sparc Disklabel type partition table
+    depends: scan_files
 #    desc: Scans the image for boot loaders (isolinux, yaboot, etc)
 errors:
   invalid-eltorito:
@@ -23,3 +34,18 @@
   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
+  apm-without-hfs:
+    type: warn
+    desc: The APM partition table doesn't have any HFS partition on it
+  invalid-mbr:
+    type: error
+    desc: MBR partition table found, but it's invalid or contains errors
+  invalid-sunlabel:
+    type: error
+    desc: Sun Disklabel partition table found, but it's invalid or contains errors
+  missing-boot-element:
+    type: error
+    desc: Some part of the boot process is missing

Modified: pancutan/tests/lib/Pancutan/Test/Booting.pm
===================================================================
--- pancutan/tests/lib/Pancutan/Test/Booting.pm	2007-08-13 07:15:06 UTC (rev 56)
+++ pancutan/tests/lib/Pancutan/Test/Booting.pm	2007-08-13 13:47:50 UTC (rev 57)
@@ -12,13 +12,126 @@
 use HTML::Entities;
 use HTML::PullParser;
 
+my %mbrtypes = ( # Taken from fdisk
+    0x00 => "Empty",
+    0x01 => "FAT12",
+    0x02 => "XENIX root",
+    0x03 => "XENIX usr",
+    0x04 => "Small FAT16",
+    0x05 => "Extended",
+    0x06 => "FAT16",
+    0x07 => "HPFS/NTFS",
+    0x08 => "AIX",
+    0x09 => "AIX bootable",
+    0x0a => "OS/2 boot mgr",
+    0x0b => "FAT32",
+    0x0c => "FAT32 LBA",
+    0x0e => "FAT16 LBA",
+    0x0f => "Extended LBA",
+    0x10 => "OPUS",
+    0x11 => "Hidden FAT12",
+    0x12 => "Compaq diag",
+    0x14 => "Hidd Sm FAT16",
+    0x16 => "Hidd FAT16",
+    0x17 => "Hidd HPFS/NTFS",
+    0x18 => "AST SmartSleep",
+    0x1b => "Hidd FAT32",
+    0x1c => "Hidd FAT32 LBA",
+    0x1e => "Hidd FAT16 LBA",
+    0x24 => "NEC DOS",
+    0x39 => "Plan 9",
+    0x3c => "PMagic recovery",
+    0x40 => "Venix 80286",
+    0x41 => "PPC PReP Boot",
+    0x42 => "SFS",
+    0x4d => "QNX4.x",
+    0x4e => "QNX4.x 2nd part",
+    0x4f => "QNX4.x 3rd part",
+    0x50 => "OnTrack DM",
+    0x51 => "OnTrackDM6 Aux1",
+    0x52 => "CP/M",
+    0x53 => "OnTrackDM6 Aux3",
+    0x54 => "OnTrack DM6",
+    0x55 => "EZ Drive",
+    0x56 => "Golden Bow",
+    0x5c => "Priam Edisk",
+    0x61 => "SpeedStor",
+    0x63 => "GNU HURD/SysV",
+    0x64 => "Netware 286",
+    0x65 => "Netware 386",
+    0x70 => "DiskSec MltBoot",
+    0x75 => "PC/IX",
+    0x80 => "Minix <1.4a",
+    0x81 => "Minix >1.4b",
+    0x82 => "Linux swap",
+    0x83 => "Linux",
+    0x84 => "OS/2 hidden C:",
+    0x85 => "Linux extended",
+    0x86 => "NTFS volume set",
+    0x87 => "NTFS volume set",
+    0x88 => "Linux plaintext",
+    0x8e => "Linux LVM",
+    0x93 => "Amoeba",
+    0x94 => "Amoeba BBT",
+    0x96 => "CHRP ISO9660",
+    0x9f => "BSD/OS",
+    0xa0 => "Thinkpad hib",
+    0xa5 => "FreeBSD",
+    0xa6 => "OpenBSD",
+    0xa7 => "NeXTSTEP",
+    0xa8 => "Darwin UFS",
+    0xa9 => "NetBSD",
+    0xab => "Darwin boot",
+    0xb7 => "BSDI fs",
+    0xb8 => "BSDI swap",
+    0xbb => "Boot Wizard Hid",
+    0xbe => "Solaris boot",
+    0xbf => "Solaris",
+    0xc1 => "DRDOS/2 FAT12",
+    0xc4 => "DRDOS/2 smFAT16",
+    0xc6 => "DRDOS/2 FAT16",
+    0xc7 => "Syrinx",
+    0xda => "Non-FS data",
+    0xdb => "CP/M / CTOS",
+    0xde => "Dell Utility",
+    0xdf => "BootIt",
+    0xe1 => "DOS access",
+    0xe3 => "DOS R/O",
+    0xe4 => "SpeedStor",
+    0xeb => "BeOS fs",
+    0xee => "EFI GPT",
+    0xef => "EFI FAT",
+    0xf0 => "Lnx/PA-RISC bt",
+    0xf1 => "SpeedStor",
+    0xf2 => "DOS secondary",
+    0xf4 => "SpeedStor",
+    0xfd => "Lnx RAID auto",
+    0xfe => "LANstep",
+    0xff => "XENIX BBT"
+);
+my %suntypes = ( # Taken from fdisk
+	0x00 => "Unassigned partition",
+	0x01 => "Boot partition",
+	0x02 => "Root filesystem",
+	0x03 => "Swap partition",
+	0x04 => "/usr filesystem",
+	0x05 => "Full-disk slice",
+	0x06 => "Stand partition",
+	0x07 => "/var filesystem",
+	0x08 => "/home filesystem",
+	0x09 => "Alt sector partition",
+	0x0a => "Cachefs partition",
+	0x0b => "SMI reserved data",
+	0x82 => "Linux SWAP",
+	0x83 => "Linux filesystem",
+	0x8e => "Linux LVM",
+	0xfd => "LInux RAID"
+);
+
 sub read_eltorito {
     my ($meta, $ncd, $scratch) = @_;
     my $file = $meta->{set}[$ncd]{file};
     my @res;
-    my %lsnidx = map {
-        $scratch->{files}{$_}{LSN} => $_
-    } keys %{$scratch->{files}};
     my $iso = Device::Cdio::ISO9660::IFS->new(
         -source => $file) or die "Error opening ISO file: $!";
     my $boot = $iso->seek_read(17,1);
@@ -104,7 +217,7 @@
             my @emucodes = qw(noemu 1.2disk 1.44disk 2.88disk hdd);
             $emul = $emucodes[$emul];
         }
-        my $bfile = $lsnidx{$lba};
+        my $bfile = $scratch->{lsnidx}{$lba};
         if($bfile) {
             push @{$meta->{set}[$ncd]{boot}{images}}, {
                 file => $bfile,
@@ -121,6 +234,11 @@
             "LBA: $lba, emulation: $emudesc, boot file: $bfile, ",
             "platform: $platform, id: $idstr");
         next unless($bootable);
+        if($emul eq "noemu") {
+            push(@{$meta->{set}[$ncd]{boot}{files}}, [ pc => $bfile ]);
+        } else {
+            push(@{$meta->{set}[$ncd]{boot}{files}}, [ pcimg => $bfile ]);
+        }
     }
     $iso->close();
     return @res;
@@ -135,6 +253,8 @@
         close($fh);
         return ();
     }
+    $meta->{set}[$ncd]{boot}{apm} = 1;
+    my @res;
     my $bs = unpack("n", substr($buf, 2, 2)); # block size
     my $nr = unpack("N", substr($buf, $bs + 4, 4)); # nr of partitions
     info("APM partition table detected: $nr partitions, block size: $bs");
@@ -142,8 +262,8 @@
     my @partitions;
     foreach(1..$nr) {
         if(substr($buf, $bs * $_, 2) ne "PM") {
-            warnn("Invalid signature in APM partition $_: ",
-                substr($buf, $bs * $_, 2));
+            push(@res, "invalid-apm", "Invalid signature in APM partition $_: "
+                . substr($buf, $bs * $_, 2));
             next;
         }
         my $start = unpack("N", substr($buf, $_ * $bs + 8, 4));
@@ -153,7 +273,8 @@
         info("APM partition $_: type: $type, name: $name, start: $start, ",
             "size: $len");
         if($_ != 1 and $start < $partitions[-1]{start}) {
-            warnn("APM partitions order doesn't match physical ordering");
+            push(@res, "invalid-apm",
+                "APM partitions order doesn't match physical ordering");
         }
         push @partitions, {
             start => $start,
@@ -164,41 +285,197 @@
     }
     @partitions = sort({ $a->{start} <=> $b->{start} } @partitions);
     if($partitions[0]{type} ne "Apple_partition_map") {
-        warnn("Invalid APM partition: first partition is type \"",
-            $partitions[0]{type}, "\"");
+        push(@res, "invalid-apm",
+            "First partition is type \"$partitions[0]{type}\"");
     }
     if($partitions[0]{start} != 1) {
-        warnn("Invalid APM partition: first partition starts in block ",
+        push(@res, "invalid-apm", "First partition starts in block " .
             $partitions[0]{start});
     }
     foreach(1..$#partitions) {
         my $start = $partitions[$_]{start};
         my $suppst = $partitions[$_-1]{start} + $partitions[$_-1]{len};
         if($start < $suppst) {
-            warnn("Invalid APM partition $_ overlaps with previous partition");
+            push(@res, "invalid-apm",
+                "Partition $_ overlaps with previous partition");
         } elsif($start != $suppst) {
-            warnn("APM partition $nr is not contiguous");
+            debug("note -- APM partition $nr is not contiguous");
         }
-        next unless($partitions[$_]{type} eq "Apple_HFS");
-        execute(hfsbootfiles => $file, $start);
     }
+    @partitions = grep({$_->{type} eq "Apple_HFS"} @partitions);
+    unless(@partitions) {
+        push(@res, "apm-without-hfs", "");
+    }
+    my @bootfiles;
+    foreach(@partitions) {
+        my($st, @files) = execute(hfsbootfiles => $file, $_->{start});
+        die "Error executing hfsbootfiles: $st\n" if($st);
+        push @bootfiles, @files;
+    }
+    foreach(@bootfiles) {
+        chomp;
+        s/^[^:]*://;
+        s/:/\//g;
+        if($scratch->{files}{$_}) {
+            info("Mac bootfile: $_");
+            push(@{$meta->{set}[$ncd]{boot}{files}}, [ mac => $_ ]);
+        } else {
+            push(@res, "unknown-boot", "Cannot find $_");
+        }
+    }
     close($fh);
-    ();
+    return @res;
 }
 sub detect_mbr_partition {
     my ($meta, $ncd, $scratch) = @_;
+    my $file = $meta->{set}[$ncd]{file};
     my $fh;
-    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, 510, 2) eq "\x55\xaa") {
+    my $buf = _myread($fh, 0, 512);
+    unless(substr($buf, 510, 2) eq "\x55\xaa") {
         close($fh);
         return ();
     }
     info("MBR partition detected");
+    my @res;
+    foreach(0..3) {
+        my $active = ord(substr($buf, 0x1be + 16 * $_, 1));
+        my $type = ord(substr($buf, 0x1be + 16 * $_ + 4, 1));
+        next unless($type);
+        if($active != 0 and $active != 0x80) {
+            push(@res, "invalid-mbr", "Active flag has invalid value $active");
+        }
+        $active = ($active != 0);
+        my $pdesc;
+        if(!exists $mbrtypes{$type}) {
+            push(@res, "invalid-mbr", "Invalid partition type $type");
+            $pdesc = "unknown";
+        } else {
+            $pdesc = $mbrtypes{$type};
+        }
+        my $start = unpack("V", substr($buf, 0x1be + 16 * $_ + 8, 4));
+        my $size = unpack("V", substr($buf, 0x1be + 16 * $_ + 12, 4));
+        if($start % 4) {
+            push(@res, "invalid-mbr", "Partition " . ($_ + 1) .
+                " points to an out of bounds block");
+        }
+        $start /= 4;
+        $size *= 512;
+        info("MBR partition: ", $_ + 1, ", type $pdesc, ",
+            "start LBA: $start, size: $size");
+        if($type == 0x96) { # CHRP
+            if($start > 0) {
+                push(@res, "invalid-mbr", "Partition type \"$pdesc\" " .
+                    "should point to the beginning of the ISO image");
+            } elsif(! $scratch->{files}{"ppc/bootinfo.txt"}) {
+                push(@res, "invalid-mbr", "Partition type is \"$pdesc\", " .
+                    "but a CHRP boot definition cannot be found");
+            } else {
+                push(@{$meta->{set}[$ncd]{boot}{files}},
+                    [ chrp => "ppc/bootinfo.txt" ]);
+                info("CHRP boot file: ppc/bootinfo.txt");
+            }
+            next;
+        } elsif($start == 0) {
+            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");
+            next;
+        }
+        my $bfile = $scratch->{lsnidx}{$start};
+        if($type == 0x41) { # PReP
+            push(@{$meta->{set}[$ncd]{boot}{files}},
+                [ prep => $bfile ]);
+            info("PReP boot file: $bfile");
+        } else {
+            push(@res, "invalid-mbr", "Partition type \"$pdesc\" points to ",
+                "$bfile, but I don't know how to handle it");
+            push(@{$meta->{set}[$ncd]{boot}{files}},
+                [ unknown => $bfile ]);
+        }
+    }
     close($fh);
-    ();
+    return @res;
 }
+sub detect_bsd_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, 0, 4)) == 0x82564557) {
+        $buf = _myread($fh, 512, 512);
+    }
+    unless(unpack("V", substr($buf, 0, 4)) == 0x82564557) {
+        close($fh);
+        return ();
+    }
+    info("BSD disklabel detected");
+    close($fh);
+    return(@res);
+}
+sub detect_sparc_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, 508, 2)) == 0xdabe) {
+        close($fh);
+        return ();
+    }
+    info("Sparc disklabel detected");
+    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 $cylsize = (unpack("n", substr($buf, 436, 2)) *
+        unpack("n", substr($buf, 438, 2)));
+    my $chksum = 0;
+    $chksum ^= $_ foreach(unpack("n*", $buf));
+    if($chksum) {
+        push(@res, "invalid-sunlabel", "Invalid checksum: $chksum");
+    }
+    if($sane != 0x600DDEEE) {
+        push(@res, "invalid-sunlabel", "Vtoc not sane: $sane");
+    }
+    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));
+        next unless($tag);
+        $bootstarts{$start} = 1; # eliminate duplicates, we only care about
+                                 # start location
+    }
+    my @bootstarts = keys(%bootstarts);
+    unless(@bootstarts) {
+        push(@res, "invalid-sunlabel", "Cannot find any valid partition");
+    }
+    foreach(@bootstarts) {
+        # This is not very clear, just in case, we try all slices
+        my $bfile = _myread($fh, $_ * $cylsize, 15 * 512);
+        if(index($bfile, "/boot/second.b") >= 0) {
+            # geez, nothing better to look for
+            info("Detected SILO bootloader");
+            if(! $scratch->{files}{"boot/second.b"}) {
+                push(@res, "missing-boot-element",
+                    "Missing SILO second stage loader");
+            } elsif(! $scratch->{files}{"boot/silo.conf"}) {
+                push(@res, "missing-boot-element",
+                    "Missing SILO configuration file");
+            } else {
+                push(@{$meta->{set}[$ncd]{boot}{files}},
+                    [ silo => "/boot/silo.conf" ]);
+            }
+        }
+    }
+    close($fh);
+    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 07:15:06 UTC (rev 56)
+++ pancutan/tests/lib/Pancutan/Test/Files.pm	2007-08-13 13:47:50 UTC (rev 57)
@@ -31,10 +31,12 @@
 }
 sub scan_files_master {
     my($global, $ncd, $scratch, $files, $lsns) = @_;
-    my %hash = map { $files->[$_] => { LSN => $lsns->[$_] } } 0..$#{$files};
-    debug(scalar keys %hash, " files found");
-    $scratch->{files} = \%hash;
+    foreach(0..$#{$files}) {
+        $scratch->{files}{$files->[$_]} = { LSN => $lsns->[$_] };
+        $scratch->{lsnidx}{$lsns->[$_]} = $files->[$_];
+    }
     $scratch->{filelist} = [ @$files ];
+    debug(scalar @$files, " files found");
     return ();
 }
 sub scan_files {




More information about the Pancutan-commits mailing list