Skip to content

Instantly share code, notes, and snippets.

@Tungstwenty
Created May 4, 2013 12:53
Show Gist options
  • Save Tungstwenty/5517424 to your computer and use it in GitHub Desktop.
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>"
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