-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathassemble_fw
executable file
·99 lines (80 loc) · 2.49 KB
/
assemble_fw
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
98
99
#!/usr/bin/perl
# Assemble a hacked firmware image for the 5D Mark 2 from
# the dumped images and the replacement user code
#
# (c) Trammell Hudson
#
use warnings;
use strict;
use Getopt::Long;
use File::Slurp;
my $user_file;
my $header_file = "5d200107.0.header.bin";
my $flasher_file = "5d200107.1.flasher.bin";
my $output_file = "5d200107_dump.fir";
my $offset = 0x5ab8;
my $pad_bytes = 24;
my $zero_bytes;
my $camera_id = 0x80000218; # 5D Mark II
GetOptions(
"header=s" => \$header_file,
"o|output=s" => \$output_file,
"flasher=s" => \$flasher_file,
"user=s" => \$user_file,
"offset=o" => \$offset,
"pad=o" => \$pad_bytes,
"z|zero+" => \$zero_bytes,
"id=o" => \$camera_id,
) or die "$0: Unknown option (read the source for options)\n";
my $header = read_file( $header_file, binmode => ':raw' )
or die "$0: Unable to open $header_file: $!\n";
my $flasher = read_file( $flasher_file, binmode => ':raw' )
or die "$0: Unable to open $flasher_file: $!\n";
my $user = '';
if( $user_file )
{
$user = read_file( $user_file, binmode=> ':raw' )
or die "$0: Unable to open $user_file: $!\n";
}
# Generate the image by concatenating everything
my $image = $header . $flasher;
my $user_len = length($user);
# Replace the user code in the image
substr( $image, $offset, $user_len ) = $user;
# Add the pad bytes to the end
$image .= (chr(0) x $pad_bytes);
# replace the camera id in the image
substr( $image, 0, 4 ) = pack( "V", $camera_id );
# Zero the rest of the bytes if the user requests it
my $zero_len = length($image) - $user_len - $offset;
substr( $image, $offset + $user_len, $zero_len ) = chr(0) x $zero_len
if $zero_bytes;
# Update the total file size
substr( $image, 0x38, 4 ) = pack( "V", length $image );
# Update the data offset and length
# Set the offset from 0x120 to 0x110. Why?
substr( $image, 0x28, 4 ) = pack( "V", 0x110 );
# Zero the CRC and recalc it
my $old_crc = unpack( "V", substr( $image, 0x20, 4 ) );
substr( $image, 0x20, 4 ) = chr(0) x 4;
my $crc = checksum( $image );
substr( $image, 0x20, 4 ) = pack( "V", $crc );
printf "$output_file: New CRC: %08x OLD %08x\n", $crc, $old_crc;
# Write out the file
write_file( $output_file, { binmode => ':raw' }, $image );
#
# This is the Worst. Checksum algorithm. Ever.
#
# It has no security or ability to detect byte order
# errors. It is literally the sum of the bytes!
#
sub checksum
{
my $image = shift;
my $sum = 0;
for( my $i=0 ; $i<length $image ; $i ++ )
{
$sum += ord( substr( $image, $i, 1 ) );
}
return ~$sum;
}