updated git and svn scripts
[xrzperl.git] / mbred
blobc302afcb656022f3146ae321ad49081ada4ca899
1 #!/usr/bin/perl -w
2 ###APPNAME: mbred
3 ###APPAUTHOR: xiaoranzzz
4 ###APPDATE: 2009-06-19 01:16:23
5 ###APPVER: 0.1
6 ###APPDESC: Edit MSDOS boot sector record
7 ###APPUSAGE: mbred [options] [bootsect_filename]
8 ###APPEXAMPLE: mbred -v bootsect.bin
9 ###APPOPTION: -v:Display bootsect detail|-d:Hex dump|-o:Set OEM ID|-b|Set bytes per sector|-s:Set sectors count|-S:Set disk size|-l:Set Label
10 use strict;
12 #ENV variable MUST be defined somewhere,
13 #FOR perl to search modules from,
14 #OR nothing will work
15 use lib $ENV{XR_PERL_MODULE_DIR};
17 use MyPlace::Script::Usage qw/help_required help_even_empty/;
18 exit 0 if(help_required($0,@ARGV));
20 use Data::Dumper;
21 my @field = qw/oem bs sc rs fat re s md sf st h hs ls pdn ch sig id vol sys/;
22 my %mbr = (
23 $field[0]=>["OEMID","STR",0x03,8,"MSDOS5.0"],
24 $field[1]=>["Bytes Per Sector","INT",0x0B,2,512],
25 $field[2]=>["Sectors Per Cluster","INT",0x0D,1,1],
26 $field[3]=>["Reserved Sectors","INT",0x0E,2,1],
27 $field[4]=>["FATs","INT",0x10,1,2],
28 $field[5]=>["Root Entries","INT",0x11,2,224],
29 $field[6]=>["Small Sectors","INT",0x13,2,2880],
30 $field[7]=>["Media Descriptor","HEX",0x15,1,"F0"],
31 $field[8]=>["Sectors Per FAT","INT",0x16,2,9],
32 $field[9]=>["Sectors Per Track","INT",0x18,2,18],
33 $field[10]=>["Heads","INT",0x1A,2,2],
34 $field[11]=>["Hidden Sectors","INT",0x1C,4,0],
35 $field[12]=>["Large Sectors","INT",0x20,4,0],
36 $field[13]=>["Physical Drive Number","INT",0x24,1,0],
37 $field[14]=>["Current Head","INT",0x25,1,0],
38 $field[15]=>["Signature","INT",0x26,1,41],
39 $field[16]=>["ID","HEX",0x27,4,"0000"],
40 $field[17]=>["Volume Label","STR",0x2B,11,"Boot"],
41 $field[18]=>["System ID","STR",0x36,8,"FAT12"]
43 my $MAXREAD = 512;
44 my $MINIREAD = 0x36+8;
46 sub hexdump {
47 my @result;
48 my $length = scalar(@_);
49 push @result," 0 1 2 3 4 5 6 7 8 9 A B C D E F\n";;
50 for(my $i = 0;$i<$length;$i+=16) {
51 my $count = $i + 16 >= $length ? $length - 1 : $i + 15;
52 my @lines = @_[$i..$count];
53 push @result,sprintf("%03X0 ",$i/16);
54 push @result,sprintf("%02X "x16,@lines);
55 push @result,map {/[\p{IsGraph} ]/ ? $_ : "." } map chr,@lines;
56 push @result,"\n";
58 push @result," 0 1 2 3 4 5 6 7 8 9 A B C D E F\n";;
59 return @result;
63 sub getvalue {
64 my $src = shift;
65 my $fn = shift;
66 my $type= $mbr{$fn}->[1];
67 my $idx = $mbr{$fn}->[2];
68 my $len = $mbr{$fn}->[3];
69 # print STDERR Dumper($mbr{$fn}),"\n";
70 my @data= @{$src}[$idx..$idx+$len-1];
71 my $i=0;
72 my $result="";
73 if($type eq "HEX") {
74 for($i..($len-1)) {
75 $result = sprintf("%02X",$data[$_]) . $result;
78 elsif($type eq "STR") {
79 $result = join("",map chr,@data);
81 else {
82 $result = 0;
83 for($i..($len-1)) {
84 $result = $result + $data[$_]*(256**$_);
87 return $result;
89 sub setvalue {
90 my $dst = shift;
91 my $fn = shift;
92 my $value = shift;
93 my $type= $mbr{$fn}->[1];
94 my $idx = $mbr{$fn}->[2];
95 my $len = $mbr{$fn}->[3];
96 # print STDERR Dumper($mbr{$fn}),"\n";
97 my @data= @{$dst}[$idx..$idx+$len-1];
98 my $i=0;
99 my $result;
100 if($type eq "HEX") {
101 $value = hex($value);
102 $type = "INT";
104 if($type eq "STR") {
105 @data = map ord,split("",substr($value . " "x$len,0,$len));
107 else {
108 @data = ();
109 for($i..($len-1)) {
110 my $low = $value % 256;
111 $value = $value / 256;
112 push @data,$low;
115 @{$dst}[$idx..$idx+$len-1]=@data;
116 return @data;
120 my %opts;
121 while(@ARGV) {
122 my $p = shift(@ARGV);
123 if($p eq '-v' or $p eq '-d') {
124 $opts{$p}=1;
125 next;
127 elsif($p =~ /^-/) {
128 $opts{$p}=shift(@ARGV);
130 else {
131 $opts{file}=$p;
135 my $bytes = "";
136 if($opts{file}) {
137 open FI,"<",$opts{file} or die("$!\n");
138 while(<FI>) {
139 $bytes .= $_;
140 last if(length($bytes)>$MAXREAD);
143 $bytes = substr($bytes . "\0" x $MINIREAD,0,$MAXREAD);
144 my @bytes = map ord,split("",$bytes);
146 foreach(@field) {
147 my $value = getvalue(\@bytes,$_);
148 my $type = $mbr{$_}->[1];
149 my $def = $mbr{$_}->[4];
150 # print STDERR ("$_ = $def\n");
151 next if($value eq $def);
152 if((!$value) or $value =~ /^[\0x0,\s]+$/) {
153 # print STDERR "Assing $_ to default:",$def,"\n";
154 setvalue(\@bytes,$_,$def);
156 else {
157 if($type eq "HEX") {
158 setvalue(\@bytes,$_,$def) if($value =~ /^0+$/);
164 setvalue(\@bytes,"oem",$opts{-o}) if($opts{-o});
165 my $secs = getvalue(\@bytes,"s");
166 my $bs = getvalue(\@bytes,"bs");
167 if($opts{-S} && $opts{-S} > 0) {
168 $opts{-S} = $opts{-S} * 1024;
169 if($opts{-b} && $opts{-b}>0) {
170 $bs = int($opts{-b});
171 $secs = int($opts{-S} / $bs);
173 elsif($opts{-s} && $opts{-s}) {
174 $secs = int($opts{-b});
175 $bs = int($opts{-S}/$secs);
177 else {
178 $secs = int($opts{-S}/$bs);
181 elsif($opts{-b} && $opts{-b}>0) {
182 $bs = int($opts{-b});
184 elsif($opts{-s} && $opts{-s}>0) {
185 $secs = int($opts{-s});
188 setvalue(\@bytes,"bs",$bs);
189 setvalue(\@bytes,"s",$secs);
190 my $size = int($secs * $bs / 1024);
191 my $tracks = 80;
192 if($size <180) {
193 setvalue(\@bytes,"h",1);
194 setvalue(\@bytes,"md","FE");
195 setvalue(\@bytes,"st",8);
196 $tracks = 40;
198 elsif($size <320) {
199 setvalue(\@bytes,"h",1);
200 setvalue(\@bytes,"md","FC");
201 setvalue(\@bytes,"st",9);
202 $tracks = 40;
204 elsif($size <360) {
205 setvalue(\@bytes,"h",1);
206 setvalue(\@bytes,"md","FA");
207 setvalue(\@bytes,"st",8);
208 $tracks = 80;
210 elsif($size <640) {
211 setvalue(\@bytes,"h",2);
212 setvalue(\@bytes,"md","FD");
213 setvalue(\@bytes,"st",9);
214 $tracks = 40;
216 elsif($size <720) {
217 setvalue(\@bytes,"h",2);
218 setvalue(\@bytes,"md","FB");
219 setvalue(\@bytes,"st",8);
221 elsif($size <1440) {
222 setvalue(\@bytes,"h",2);
223 setvalue(\@bytes,"md","F9");
224 setvalue(\@bytes,"st",9);
226 elsif($size <2880) {
227 setvalue(\@bytes,"h",2);
228 setvalue(\@bytes,"md","F0");
229 setvalue(\@bytes,"st",18);
231 elsif($size ==2880) {
232 setvalue(\@bytes,"h",2);
233 setvalue(\@bytes,"md","F0");
234 setvalue(\@bytes,"st",36);
235 setvalue(\@bytes,"sc",2);
237 elsif($size <260000) {
238 setvalue(\@bytes,"sc",1);
240 else {
241 setvalue(\@bytes,"sc",4);
244 if($opts{-v}) {
245 foreach(@field) {
246 printf STDERR "%28s : ",$mbr{$_}->[0];
247 print STDERR getvalue(\@bytes,$_),"\n";
250 if($opts{-d}) {
251 print STDERR hexdump(@bytes),"\n";
254 print map chr,@bytes;# unless($opts{-v} or $opts{-d});