summaryrefslogtreecommitdiffstats
path: root/contrib/mntnbi/mntnbi.pl
blob: 55b8148439c4977082835890517edebad25cf8d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/perl -w
#
# Quick Perl program to decode and display details about 
# tagged images created by mknbi, and then mount the contained
# DOS filesystem using a loop-back mount
#
# Martin Atkins, November 1998
# by hacking disnbi by
# Ken Yap, September 1998
#
#

sub getvendordata {
	my ($flags) = @_;

	my $vendordata = '';
	my $vendorlen = ($flags & 0xff) >> 4;
	if ($vendorlen > 0) {
		$vendorlen *= 4;
		$vendordata = unpack("A$vendorlen", substr($imageheader, $curoffset));
		$curoffset += $vendorlen;
	}
	return ($vendordata);
}

sub decodesegmentflags {
	my ($flags) = @_;

	$flags >>= 24;
	$flags &= 0x3;
	($flags == 0) and $type = "Absolute";
	($flags == 1) and $type = "Follows last segment";
	($flags == 2) and $type = "Below end of memory";
	($flags == 3) and $type = "Below last segment loaded";
	return ($type);
}

sub onesegment
{
	my ($segnum) = @_;
	my ($type, $vendordata);

	my ($flags, $loadaddr, $imagelen, $memlength) = unpack("V4", substr($imageheader, $curoffset));
	$curoffset += 16;
	print "Segment number $segnum\n";
	printf "Load address:\t\t%08x\n", $loadaddr;
	printf "Image length:\t\t%d\n", $imagelen;
	printf "Memory length:\t\t%d\n", $memlength;
	$type = &decodesegmentflags($flags);
	printf "Position:\t\t$type\n";
	printf "Vendor tag:\t\t%d\n", ($flags >> 8) & 0xff;
	if (($vendordata = &getvendordata($flags)) ne '') {
		print "Vendor data:\t\t", $vendordata, "\n";
	}
	print "\n";
	push (@seglengths, $imagelen);
	return (($flags >> 26) & 1);
}

@seglengths = ();
$#ARGV == 1 or die "Usage: mntnbi tagged-image-file dir\n";
$imagefile= $ARGV[0];
open(I, $ARGV[0]) or die "$imagefile: $!\n";
(defined($status = sysread(I, $imageheader, 512)) and $status == 512)
	or die "$imagefile: Cannot read header\n";
$headerrecord = substr($imageheader, 0, 16);
($magic, $flags, $bx, $ds, $ip, $cs) = unpack("a4Vv4", $headerrecord);
$magic eq "\x36\x13\x03\x1B" or die "$imagefile: Not a tagged image file\n";
$curoffset = 16;

# Now decode the header

printf "Header location:\t%04x:%04x\n", $ds, $bx;
printf "Start address:\t\t%04x:%04x\n", $cs, $ip;
printf "Flags:\n";
	print "Return to loader after execution (extension)\n" if (($flags >> 8) &  1);
if (($vendordata = &getvendordata($flags)) ne '') {
	print "Vendor data:\t\t", $vendordata, "\n";
}
print "\n";

# Now decode each segment record

$segnum = 1;
do {
	$lastrecord = &onesegment($segnum);
	++$segnum;
} while (!$lastrecord);

if ($#seglengths != 1) {
	die "This is not a DOS image $#seglengths\n";
}
$offset = 512 + $seglengths[0];
print "mounting filesystem at offset $offset in $ARGV[0] on $ARGV[1]\n";
$rc = system "mount $ARGV[0] $ARGV[1] -t msdos -o loop,offset=$offset";
print "Done\n" if ($rc == 0);
exit(0);