Tuesday, October 1, 2013

disaster recovery on android phones

hi guys,
i had a problem with a customer phone and flashing roms, radios and all that stuff doesn't help at all.
so i decided to do a nandroid restore in my own way.

first of all here you are what you need:
- good knowledge of linux common commands/tools
- the damaged phone ( with recovery accessible )
- a good phone of the same model [ optional ]

you don't need a good phone if you already make a dd backup of the damaged one when it was running fine ( explained later ).
NOTE: if you got some connection error while launching netcat ( nc ) try to run the adb forward command again from another shell.

step 1

read from good


first of all we need to read the whole emmc from the good phone ( i suggest to do this in recovery, when your phone doesn't use emmc so much ):
adb forward tcp:4444 tcp:4444
adb shell
su
nc -l -p 4444 -e dd if=/dev/block/mmcblk0
now, from another shell:
adb forward tcp:4444 tcp:4444
nc 127.0.0.1 4444 > backup.dd
...wait...
congratulations! now you have a bulletproof backup of a phone.

setp 2

understand where is the recovery

since you are going to overwrite the whole emmc you must be sure to not overwrite something that is in use while you are doing the restore job.
so, you need a lot of oil for your brain gears.
2 hints that will save you hours of googling: /proc/emmc or /proc/mtd have the names of your partitions, and /proc/partitions have their sizes.
so, after you figured out which partition is the recovery one, lets find out where it starts in our backup.
use fdisk -l on the bakup image ( backup.dd ) to find out where our recovery starts.
here is my output:
Warning: omitting partitions after #60.
They will be deleted if you save this partition table.
Disk mmcblk0: 15.6 GB, 15634268160 bytes, 30535680 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
        Device Boot      Start         End      Blocks   Id  System
mmcblk0p1   *           1         256         128   4d  QNX4.x
mmcblk0p2             257         768         256   51  OnTrack DM6 Aux1
mmcblk0p3             769      262110      130671   5d  Unknown
mmcblk0p4          262111    30535678    15136784    5  Extended
mmcblk0p5          262112      262143          16   5a  Unknown
mmcblk0p6          262145      262656         256   73  Unknown
mmcblk0p7          262658      293812       15577+  5b  Unknown
mmcblk0p8          293814      294325         256   5c  Priam Edisk
mmcblk0p9          294327      296374        1024   45  Unknown
mmcblk0p10         296376      296887         256   47  Unknown
mmcblk0p11         296889      300984        2048   46  Unknown
mmcblk0p12         300986      303033        1024   4c  Unknown
mmcblk0p13         303035      303098          32    0  Empty
mmcblk0p14         303100      315387        6144   34  Unknown
mmcblk0p15         315389      317436        1024   36  Unknown
mmcblk0p16         317438      319485        1024    0  Empty
mmcblk0p17         319487      411646       46080   77  Unknown
mmcblk0p18         411648      432127       10240   7a  Unknown
mmcblk0p19         432129      442368        5120    0  Empty
mmcblk0p20         442370      458750        8190+  74  Unknown
mmcblk0p21         458752      491519       16384   48  Unknown
mmcblk0p22         491521      524287       16383+  71  Unknown
mmcblk0p23         524289      526333        1022+  76  Unknown
mmcblk0p24         526335      534526        4096   4a  Unknown
mmcblk0p25         534528      542719        4096   4b  Unknown
mmcblk0p26         542721      583680       20480   19  Unknown
mmcblk0p27         583682      583689           4    0  Empty
mmcblk0p28         583691      584202         256   23  Unknown
mmcblk0p29         584204      584235          16    0  Empty
mmcblk0p30         584237      586797        1280+   0  Empty
mmcblk0p31         586799      586926          64    0  Empty
mmcblk0p32         586928      786431       99752    0  Empty
mmcblk0p33         786433     4194302     1703935   83  Linux
mmcblk0p34        4194304     4718590      262143+  83  Linux
mmcblk0p35        4718592    30408703    12845056   83  Linux
mmcblk0p36       30408705    30508704       50000    c  W95 FAT32 (LBA)
mmcblk0p37         262112      262143          16   5a  Unknown
mmcblk0p38         262145      262656         256   73  Unknown
mmcblk0p39         262658      293812       15577+  5b  Unknown
[garbage truncated...]


NOTE: there is a lot of garbage, if you known that there is 36 partitions, just ignore everything comes after.

for me the recovery partition is the 22.
my partition start at block #491521 ( NOTE that i wrote block, not byte ).
you HAVE TO run some test before start writing, to be sure that your offset/sizes are correct.
[from adb]
dd if=/dev/block/mmcblk0 count=1 of=/dev/null
this will return how many bytes are stored in one block of your emmc, the BLOCK_SIZE.
now the output from your workstation:
dd if=backup.dd bs=1 skip=$(( START_BLOCK * BLOCK_SIZE )) count=100 | hexdump -C
should be the same of this command from adb:
dd if=RECOVERY_PARTITION bs=1 count=100 | hexdump -C
replace:
START_BLOCK with the block # where your partition starts ( 491521 for me )
BLOCK_SIZE with the size of one bolck of your emmc
RECOVERY_PARTITION with the partition to where the recovery it's stored ( /dev/block/mmcblk0p22 for me )

is it all ok? is everything correct? are you sure?
well, just for be very sure of what we are going to do let's test the next important address.
let's check that the recovery partition ends where we think that it will.
from the fdisk output let's take the start block of the partition next to the recovery one.
for me it's partition 23 ( 22 + 1 ), which start on #524289, it will be our END_BLOCK.
now repeat the previous commands changing partition number and start_block.
you should have the same output from adb and your workstation.

step 3

writing to damaged phone

we are now ready to write the whole good emmc to the damaged phone, skipping the recovery partition.
let's do this.
reboot the damaged phone into recovery.
start copying everything before the recovery.
adb forward tcp:4444 tcp:4444
adb shell
su
nc -l -p 4444 -e dd bs=1 of=/dev/block/mmcblk0
from another shell:
adb forward tcp:4444 tcp:4444
dd if=backup.dd bs=1 count=$(( START_BLOCK * BLOCK_SIZE )) | nc 127.0.0.1 4444
...wait...
let's copy everything after the recovery partition:
[from adb]
nc -l -p 4444 -e dd bs=1 seek=$((END_BLOCK * BLOCK_SIZE )) of=/dev/block/mmcblk0
from your workstation:
dd if=backup.dd bs=1 skip=$(( END_BLOCK * BLOCK_SIZE )) | nc 127.0.0.1 4444
PS: ignore dd warnings about lseek64 if any.
that's all folks!

if your device still KO please ensure to change device specific data.
for example HTC writes the phone IMEI into /dev/bock/mmcblk0p4 ( facepalm )

please ask for device-specific partitions in the device forum on XDA.

for any question feel free to comment this post, i'll answer ASAP.

-- tux_mind

2 comments:

  1. Thank you for your tutorial. I restored a full mmcblk0 backup on my Note2 (N7105). I booted into CWM Recovery and I noticed that the recovery partition is not mounted, it's running from the memory. This way I could easily overwrite the full mmcblk0, including the recovery partition.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete