Initial revision
[people/sha0/gpxe.git] / contrib / mntnbi / mntnbi.pl
1 #!/usr/bin/perl -w
2 #
3 # Quick Perl program to decode and display details about 
4 # tagged images created by mknbi, and then mount the contained
5 # DOS filesystem using a loop-back mount
6 #
7 # Martin Atkins, November 1998
8 # by hacking disnbi by
9 # Ken Yap, September 1998
10 #
11 #
12
13 sub getvendordata {
14         my ($flags) = @_;
15
16         my $vendordata = '';
17         my $vendorlen = ($flags & 0xff) >> 4;
18         if ($vendorlen > 0) {
19                 $vendorlen *= 4;
20                 $vendordata = unpack("A$vendorlen", substr($imageheader, $curoffset));
21                 $curoffset += $vendorlen;
22         }
23         return ($vendordata);
24 }
25
26 sub decodesegmentflags {
27         my ($flags) = @_;
28
29         $flags >>= 24;
30         $flags &= 0x3;
31         ($flags == 0) and $type = "Absolute";
32         ($flags == 1) and $type = "Follows last segment";
33         ($flags == 2) and $type = "Below end of memory";
34         ($flags == 3) and $type = "Below last segment loaded";
35         return ($type);
36 }
37
38 sub onesegment
39 {
40         my ($segnum) = @_;
41         my ($type, $vendordata);
42
43         my ($flags, $loadaddr, $imagelen, $memlength) = unpack("V4", substr($imageheader, $curoffset));
44         $curoffset += 16;
45         print "Segment number $segnum\n";
46         printf "Load address:\t\t%08x\n", $loadaddr;
47         printf "Image length:\t\t%d\n", $imagelen;
48         printf "Memory length:\t\t%d\n", $memlength;
49         $type = &decodesegmentflags($flags);
50         printf "Position:\t\t$type\n";
51         printf "Vendor tag:\t\t%d\n", ($flags >> 8) & 0xff;
52         if (($vendordata = &getvendordata($flags)) ne '') {
53                 print "Vendor data:\t\t", $vendordata, "\n";
54         }
55         print "\n";
56         push (@seglengths, $imagelen);
57         return (($flags >> 26) & 1);
58 }
59
60 @seglengths = ();
61 $#ARGV == 1 or die "Usage: mntnbi tagged-image-file dir\n";
62 $imagefile= $ARGV[0];
63 open(I, $ARGV[0]) or die "$imagefile: $!\n";
64 (defined($status = sysread(I, $imageheader, 512)) and $status == 512)
65         or die "$imagefile: Cannot read header\n";
66 $headerrecord = substr($imageheader, 0, 16);
67 ($magic, $flags, $bx, $ds, $ip, $cs) = unpack("a4Vv4", $headerrecord);
68 $magic eq "\x36\x13\x03\x1B" or die "$imagefile: Not a tagged image file\n";
69 $curoffset = 16;
70
71 # Now decode the header
72
73 printf "Header location:\t%04x:%04x\n", $ds, $bx;
74 printf "Start address:\t\t%04x:%04x\n", $cs, $ip;
75 printf "Flags:\n";
76         print "Return to loader after execution (extension)\n" if (($flags >> 8) &  1);
77 if (($vendordata = &getvendordata($flags)) ne '') {
78         print "Vendor data:\t\t", $vendordata, "\n";
79 }
80 print "\n";
81
82 # Now decode each segment record
83
84 $segnum = 1;
85 do {
86         $lastrecord = &onesegment($segnum);
87         ++$segnum;
88 } while (!$lastrecord);
89
90 if ($#seglengths != 1) {
91         die "This is not a DOS image $#seglengths\n";
92 }
93 $offset = 512 + $seglengths[0];
94 print "mounting filesystem at offset $offset in $ARGV[0] on $ARGV[1]\n";
95 $rc = system "mount $ARGV[0] $ARGV[1] -t msdos -o loop,offset=$offset";
96 print "Done\n" if ($rc == 0);
97 exit(0);