Created
May 4, 2013 12:53
-
-
Save Tungstwenty/5517424 to your computer and use it in GitHub Desktop.
Parser for the contents of Xperia Z's TA partition, in line with the discussion at http://forum.xda-developers.com/showthread.php?t=2234627 Run with "java -cp . DumpXperiaTA <path_to_dump_file>"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.EOFException; | |
/** | |
* Parser for the tokens found in Xperia Z's TA partition. | |
* <p> | |
* | |
* Dump the partition by storing the contents of /dev/block/mmcblk0p1, | |
* and pass that file as input parameter to this class. | |
* | |
* @author Tungstwenty | |
* @see http://forum.xda-developers.com/showthread.php?t=2234627 | |
*/ | |
public class DumpXperiaTA { | |
public static void main(String[] args) throws Exception { | |
if (args.length != 1) { | |
System.out.println("Usage: " + | |
"java -cp ... " + DumpXperiaTA.class.getName() + " path_to_TA_dump_file"); | |
System.exit(1); | |
} | |
String input = args[0]; | |
File dmpFile = new File(input); | |
CountingInputStream is = new CountingInputStream(new FileInputStream(dmpFile)); | |
System.out.println("Start dumping " + input + "\n"); | |
StringBuffer sbAsciiValue = new StringBuffer(); | |
for (;;) { | |
long pos = is.getByteCount(); | |
int tokenId; | |
try { | |
tokenId = readInt(is); | |
} catch (EOFException ex) { | |
// No more bytes on the file | |
break; | |
} | |
System.out.printf("Offset: 0x%08X\n", pos); | |
if (tokenId == 0x3BF8E9C1) { | |
int headerValue1 = readInt(is); | |
int headerValue2 = readInt(is); | |
System.out.printf("Found block header 0x%8X, 0x%8X, 0x%8x\n\n", tokenId, headerValue1, headerValue2); | |
continue; | |
} | |
int length = readInt(is); | |
int tokenMagic1 = readInt(is); | |
int tokenMagic2 = readInt(is); | |
if (tokenMagic1 != 0x3BF8E9C1) { | |
// Skip till the start of the next block | |
if (pos % 0x20000 == 0) { | |
System.out.println("Skipping empty block"); | |
} else { | |
System.out.println("Skipping unused part of the block"); | |
} | |
pos = is.getByteCount(); | |
while ((pos % 0x20000) != 0) { | |
readInt(is); | |
pos += 4; | |
} | |
System.out.print("\n\n"); | |
continue; | |
} | |
System.out.printf("Token 0x%08X, Len = 0x%08X, Magic1 = 0x%08X, Magic2 = 0x%08X\n", tokenId, length, tokenMagic1, tokenMagic2); | |
byte[] value = new byte[length]; | |
readFully(is, value); | |
sbAsciiValue.setLength(0); | |
System.out.println("Hex value:"); | |
int colAscii = 0; | |
for (int i = 0; i < length; i++) { | |
System.out.printf("%02X", value[i]); | |
if (i % 40 == 39) | |
// Line break after every 80 hex chars | |
System.out.println(); | |
if (value[i] >= 32 || value[i] == 0x0A) { | |
sbAsciiValue.append((char) value[i]); | |
} else { | |
sbAsciiValue.append('.'); | |
} | |
colAscii = (value[i] == 0x0A) ? 0 : colAscii + 1; | |
if (colAscii > 79) { | |
sbAsciiValue.append((char) 0x0A); | |
colAscii = 0; | |
} | |
} | |
System.out.println("\nASCII value:"); | |
System.out.println(sbAsciiValue.toString()); | |
System.out.print("\n\n"); | |
if (length % 4 != 0) { | |
int padding = 4 - length % 4; | |
for (int i = 0; i < padding; i++) { | |
if (is.read() != 0xFF) | |
throw new IOException("Failure while expecting padding 0xFF"); | |
} | |
} | |
} | |
System.out.println("File read successfully"); | |
is.close(); | |
} | |
private static int readInt(InputStream is) throws IOException { | |
int result = 0; | |
for (int i = 0; i < 4; i++) { | |
int byt = is.read(); | |
if (byt < 0) | |
throw new EOFException(); | |
result |= byt << (i * 8); | |
} | |
return result; | |
} | |
private static void readFully(InputStream in, byte b[]) throws IOException { | |
readFully(in, b, 0, b.length); | |
} | |
private static void readFully(InputStream in, byte b[], int off, int len) throws IOException { | |
if (len < 0) | |
throw new IndexOutOfBoundsException(); | |
int n = 0; | |
while (n < len) { | |
int count = in.read(b, off + n, len - n); | |
if (count < 0) | |
throw new EOFException(); | |
n += count; | |
} | |
} | |
private static String getHexString(long value, int bytes) { | |
int byt; | |
int i; | |
StringBuffer result = new StringBuffer(); | |
final String HEX_CHARS = "0123456789ABCDEF"; | |
for (i = bytes - 1; i >= 0; i--) { | |
byt = (int) (value >> (i * 8)) & 0xFF; | |
result.append(HEX_CHARS.charAt((byt & 0xF0) >> 4)); | |
result.append(HEX_CHARS.charAt(byt & 0x0F)); | |
} | |
return result.toString(); | |
} | |
// Input stream that tracks the number of bytes read | |
// From Apache commons-io | |
public static class CountingInputStream extends FilterInputStream { | |
private long count; | |
public CountingInputStream(InputStream in) { | |
super(in); | |
} | |
@Override | |
public int read(byte[] b) throws IOException { | |
int found = super.read(b); | |
this.count += (found >= 0) ? found : 0; | |
return found; | |
} | |
@Override | |
public int read(byte[] b, int off, int len) throws IOException { | |
int found = super.read(b, off, len); | |
this.count += (found >= 0) ? found : 0; | |
return found; | |
} | |
@Override | |
public int read() throws IOException { | |
int found = super.read(); | |
this.count += (found >= 0) ? 1 : 0; | |
return found; | |
} | |
@Override | |
public long skip(final long length) throws IOException { | |
final long skip = super.skip(length); | |
this.count += skip; | |
return skip; | |
} | |
public synchronized long getByteCount() { | |
return this.count; | |
} | |
public synchronized long resetByteCount() { | |
long tmp = this.count; | |
this.count = 0; | |
return tmp; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment