From e4f59704dafdd21d994d8cd47d1770b640f2cf84 Mon Sep 17 00:00:00 2001 From: Hamish Coleman Date: Fri, 22 Apr 2016 16:50:48 +1000 Subject: [PATCH] Add infrastructure for applying patches --- Makefile | 13 +- hexpatch.pl | 196 ++++++++++++++++++ x230.G2HT35WW.img.d/001_keysym.patch | 22 ++ x230.G2HT35WW.img.d/002_dead_keys.patch | 16 ++ .../003_keysym_replacements.patch | 16 ++ x230.G2HT35WW.img.d/004_fn_keys.patch | 24 +++ 6 files changed, 284 insertions(+), 3 deletions(-) create mode 100755 hexpatch.pl create mode 100644 x230.G2HT35WW.img.d/001_keysym.patch create mode 100644 x230.G2HT35WW.img.d/002_dead_keys.patch create mode 100644 x230.G2HT35WW.img.d/003_keysym_replacements.patch create mode 100644 x230.G2HT35WW.img.d/004_fn_keys.patch diff --git a/Makefile b/Makefile index a24af7b..e75916e 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,17 @@ install.radare.projects: # keep intermediate files .PRECIOUS: %.img.orig -# Generate a working file that we can patch +# Generate a working file with any known patches applied %.img: %.img.orig - sha1sum -c $<.sha1 - cp $< $@ + cp --reflink=auto $< $@ + [ -d $@.d ] && for i in $@.d/*.patch; do ./hexpatch.pl $$i $@; done + +%.hex: % + hd -v $< >$@ + +# Generate a patch report +%.diff: %.hex %.orig.hex + -diff -u $(basename $@).orig.hex $(basename $@).hex >$@ mec-tools/Makefile: git submodule update --init --remote diff --git a/hexpatch.pl b/hexpatch.pl new file mode 100755 index 0000000..9028fed --- /dev/null +++ b/hexpatch.pl @@ -0,0 +1,196 @@ +#!/usr/bin/env perl +use warnings; +use strict; +# +# Apply a diff of two hexdumps as a binary patch + +use IO::File; + +use Data::Dumper; +$Data::Dumper::Indent = 1; +$Data::Dumper::Sortkeys = 1; +$Data::Dumper::Quotekeys = 0; + +sub usage() { + print("This utility will take a diff of two hexdumps and can apply\n"); + print("the binary changes to the original binary file, using the\n"); + print("context lines to provide data to match and confirm we are\n"); + print("patching the right file\n"); + print("\n"); + print("Usage:\n"); + print(" hexpatch.pl patchfile binaryfile\n"); + print("\n"); + exit(1); +} + +sub parse_hexline { + my $line = shift; + + my $addr; + my $binary; + + my @fields = split(/\s+/,$line); + + if ($fields[0] !~ m/^([0-9a-fA-F])+$/) { + return undef; + } + $addr = hex($fields[0]); + shift @fields; + + while (defined($fields[0]) && $fields[0] =~ m/^([0-9a-fA-F])+$/) { + $binary .= chr(hex($fields[0])); + shift @fields; + } + + return ($addr,$binary); +} + +sub read_patchfile { + my $filename = shift; + + my $fh = IO::File->new($filename, O_RDONLY); + if (!defined($fh)) { + return undef; + } + + my $db = {}; + + my $seen_at_symbols = 0; + + while(<$fh>) { + # anything before we see a starting at symbol line can be ignored + if (!$seen_at_symbols) { + if (m/^\@\@ .* \@\@$/) { + $seen_at_symbols = 1; + } + next; + } + + my $addr; + my $binary; + my $type; + if (m/^([-+ ])(.*)/) { + # a context, oldfile or newfile line + $type = $1; + ($addr, $binary) = parse_hexline($2); + } elsif (m/^\@\@ .* \@\@$/) { + # hunk separator - we can ignore it since we use the hex addr + next; + } else { + warn("Invalid prefix in patchfile"); + # TODO - linenumber + return(undef); + } + + if (!defined($addr)) { + warn("Invalid data in hexline"); + # TODO - linenumber + return(undef); + } + + if (!defined($binary)) { + # this line was empty of data + next; + } + + if ($type eq ' ') { + $type = 'context'; + } elsif ($type eq '-') { + $type = 'old'; + } elsif ($type eq '+') { + $type = 'new'; + } + + if (defined($db->{addr}{$addr}{$type})) { + warn("Duplicate address in hexdata"); + # TODO - linenumber + return(undef); + } + + $db->{addr}{$addr}{$type} = $binary; + } + return $db; +} + +sub verify_context { + my $db = shift; + my $fh = shift; + + for my $addr (sort keys(%{$db->{addr}})) { + my $entry = $db->{addr}{$addr}; + my $expected; + if ($entry->{context}) { + $expected = $entry->{context}; + } elsif ($entry->{old}) { + $expected = $entry->{old}; + } elsif ($entry->{new}) { + warn("Address $addr has new data but no old data\n"); + return undef; + } else { + # No data of any kind here, just skip it + next; + } + + my $found; + $fh->seek($addr,SEEK_SET); + $fh->read($found,length($expected)); + + if ($found ne $expected) { + warn("Address $addr mismatched data\n"); + return undef; + } + } + return 1; +} + +sub apply_patch { + my $db = shift; + my $fh = shift; + + for my $addr (sort keys(%{$db->{addr}})) { + my $entry = $db->{addr}{$addr}; + + my $newdata; + if ($entry->{new}) { + $newdata = $entry->{new}; + } else { + # No data to write at this address, just skip it + next; + } + + $fh->seek($addr,SEEK_SET); + $fh->print($newdata); + + } +} + +sub main() { + my $patchfile = shift @ARGV; + my $binaryfile = shift @ARGV; + + if (!defined($patchfile) or !defined($binaryfile)) { + usage(); + } + + my $db = read_patchfile($patchfile); + + if (!defined($db)) { + warn("Cannot read $patchfile\n"); + exit(1); + } + + my $fh = IO::File->new($binaryfile, O_RDWR); + if (!defined($fh)) { + warn("Could not open binaryfile\n"); + exit(1); + } + + if (!verify_context($db,$fh)) { + warn("The binaryfile does not match the context bytes from the patch"); + exit(1); + } + + apply_patch($db,$fh); +} +main(); + diff --git a/x230.G2HT35WW.img.d/001_keysym.patch b/x230.G2HT35WW.img.d/001_keysym.patch new file mode 100644 index 0000000..02c601d --- /dev/null +++ b/x230.G2HT35WW.img.d/001_keysym.patch @@ -0,0 +1,22 @@ +This updates the keyboard matrix scancode table. + +Copied directly from the x220 firmware + +@@ keysym @@ + 00021930 00 00 00 00 00 00 00 00 77 0a 19 76 27 84 36 85 |........w..v'.6.| + 00021940 00 00 00 00 00 00 00 00 0c 0b 1a 1b 28 29 2a 37 |............()*7| + 00021950 00 00 00 00 00 00 00 00 78 79 0e 0f 1d 74 2b 3d |........xy...t+=| +-00021960 00 00 00 00 00 00 00 00 00 7b 00 9b 00 00 00 59 |.........{.....Y| +-00021970 00 00 00 00 00 00 00 00 50 7a 9a 99 98 97 a0 54 |........Pz.....T| +-00021980 00 00 00 00 00 00 00 00 4c 4b 00 00 7c 00 55 56 |........LK..|.UV| +-00021990 00 00 00 00 00 00 00 00 00 51 00 00 00 53 00 4f |.........Q...S.O| +-000219a0 00 00 00 00 00 00 00 00 00 00 00 00 00 3c 00 3e |.............<.>| ++00021960 00 00 00 00 00 00 00 00 4b 7b 00 9b 00 00 00 59 |........K{.....Y| ++00021970 00 00 00 00 00 00 00 00 4c 7a 9a 99 98 97 a0 54 |........Lz.....T| ++00021980 00 00 00 00 00 00 00 00 55 56 00 00 9c 00 89 8a |........UV......| ++00021990 00 00 00 00 00 00 00 00 50 51 00 00 00 53 7e 4f |........PQ...S~O| ++000219a0 00 00 00 00 00 00 00 00 00 7c 7d 00 00 3c 00 3e |.........|}..<.>| + 000219b0 00 00 00 00 00 00 00 00 00 00 00 2c 00 00 39 00 |...........,..9.| + 000219c0 00 00 00 00 00 00 00 00 3a 00 00 00 00 00 40 00 |........:.....@.| + 000219d0 00 00 00 00 00 00 00 96 00 9d 00 9e 9f 4a 3a 9c |.............J:.| + 000219e0 7d 7e 00 00 00 00 00 00 ff 00 7f 00 7f 00 ff 00 |}~..............| diff --git a/x230.G2HT35WW.img.d/002_dead_keys.patch b/x230.G2HT35WW.img.d/002_dead_keys.patch new file mode 100644 index 0000000..10aefec --- /dev/null +++ b/x230.G2HT35WW.img.d/002_dead_keys.patch @@ -0,0 +1,16 @@ +This updates the bitmap of live/dead keys to enable the missing keys + +Copied directly from the x220 firmware + +@@ dead_keys @@ + 000219b0 00 00 00 00 00 00 00 00 00 00 00 2c 00 00 39 00 |...........,..9.| + 000219c0 00 00 00 00 00 00 00 00 3a 00 00 00 00 00 40 00 |........:.....@.| + 000219d0 00 00 00 00 00 00 00 96 00 9d 00 9e 9f 4a 3a 9c |.............J:.| + 000219e0 7d 7e 00 00 00 00 00 00 ff 00 7f 00 7f 00 ff 00 |}~..............| +-000219f0 ff 00 ff 00 ff 00 ff 00 ff 00 8a 00 ff 00 d3 00 |................| +-00021a00 a2 00 a0 00 48 00 41 80 fa 03 00 00 a0 97 00 00 |....H.A.........| ++000219f0 ff 00 ff 00 ff 00 ff 00 ff 00 8b 00 ff 00 d3 00 |................| ++00021a00 e3 00 a6 00 48 00 41 80 fa 03 00 00 a0 97 00 00 |....H.A.........| + 00021a10 10 01 00 00 d8 18 02 00 e8 19 02 00 0c 1a 02 00 |................| + 00021a20 ff 43 41 3f 3d 3b 3c 58 64 44 42 40 3e 0f 29 59 |.CA?=;.)Y| + 00021a30 65 38 2a 70 1d 10 02 5a 66 71 2c 1f 1e 11 03 5b |e8*p...Zfq,....[| diff --git a/x230.G2HT35WW.img.d/003_keysym_replacements.patch b/x230.G2HT35WW.img.d/003_keysym_replacements.patch new file mode 100644 index 0000000..814f188 --- /dev/null +++ b/x230.G2HT35WW.img.d/003_keysym_replacements.patch @@ -0,0 +1,16 @@ +This updates the table of "simple replacements", fixing the multimedia keys +and the seventh row Fn combos + +Copied directly from the x220 firmware + +@@ keysym_replacements @@ + 00021860 5b 60 65 5f 00 00 00 00 00 00 00 00 00 00 00 5c |[`e_...........\| + 00021870 61 66 64 00 00 00 00 00 00 00 00 00 00 5d 62 67 |afd..........]bg| + 00021880 69 00 00 6c 00 00 00 00 00 00 00 00 63 00 68 6a |i..l........c.hj| +-00021890 00 00 00 00 00 00 00 00 79 6d 00 7a 58 00 7b 6f |........ym.zX.{o| +-000218a0 00 32 46 02 20 44 01 26 7d 00 1a 7e 00 00 00 00 |.2F. D.&}..~....| ++00021890 00 00 00 00 00 00 00 00 7c 44 01 7d 5a 00 7e 46 |........|D.}Z.~F| ++000218a0 02 4f 6d 00 53 6b 00 54 58 00 59 6f 00 00 00 00 |.Om.Sk.TX.Yo....| + 000218b0 9e 9e 00 9f 9f 00 4a 4a 00 00 00 00 b2 00 00 00 |......JJ........| + 000218c0 b4 16 02 00 40 00 00 00 58 18 02 00 18 18 02 00 |....@...X.......| + 000218d0 0b 00 00 00 98 18 02 00 01 02 11 10 1f 6e 2e 83 |.............n..| diff --git a/x230.G2HT35WW.img.d/004_fn_keys.patch b/x230.G2HT35WW.img.d/004_fn_keys.patch new file mode 100644 index 0000000..6ae138f --- /dev/null +++ b/x230.G2HT35WW.img.d/004_fn_keys.patch @@ -0,0 +1,24 @@ +This fixes the table of Fn key combos with "more complex" functions. This +fixes most of the Fn+F key codes. + +Specifically missing is F12, as I was uncertain about the "action" byte to +be used for it. + +Also, with this patch, the Fn+F3 generates a Screen Lock code. + +Used the x220 table as a template as the "action" byte values have changed from +the old firmware + +@@ fn_keys @@ + 00021640 5a 00 00 00 ff ff 00 00 00 00 00 00 9c 8e 01 00 |Z...............| + 00021650 a0 8e 01 00 a4 8e 01 00 a8 8e 01 00 ac 8e 01 00 |................| + 00021660 98 f4 01 00 b0 8e 01 00 b4 8e 01 00 c0 70 c0 71 |.............p.q| +-00021670 c0 72 c7 73 e4 78 e5 77 c0 76 c0 00 c0 00 c0 97 |.r.s.x.w.v......| +-00021680 c0 00 c8 00 c0 02 c0 03 00 00 c6 3d 00 00 00 00 |...........=....| +-00021690 00 00 c0 00 c0 74 c0 75 00 00 00 00 00 00 00 00 |.....t.u........| ++00021670 c0 72 c7 73 e4 50 e5 51 c0 76 c0 77 c0 78 c0 97 |.r.s.P.Q.v.w.x..| ++00021680 c0 7a c8 00 c0 02 c0 03 00 00 c6 55 00 00 00 00 |.z.........U....| ++00021690 00 00 c0 3d c0 74 c0 75 00 00 00 00 00 00 00 00 |...=.t.u........| + 000216a0 c0 a0 00 00 08 00 00 00 4c 16 02 00 1b 00 00 00 |........L.......| + 000216b0 6c 16 02 00 00 00 00 0e 00 16 00 1e 00 26 00 25 |l............&.%| + 000216c0 00 2e 00 36 00 3d 00 3e 00 46 00 45 00 4e 00 55 |...6.=.>.F.E.N.U|