Como fazer backup do Android no tablet BC1003 (Wei Wide PRO 10″)

About BC1003O tablet BC1003 usa chip Allwinner A10, um processador ARM extremamente hackeável. No entanto, brincar com isto pode ser perigoso pelo risco de “brickar” (transformar num tijolo de alta tecnologia) o dispositivo. Mas o Allwinner é praticamente à prova de tijolamento, desde que se tenha as ROMs originais e se possa queimá-las de volta no tablet. Como o fabricante Yones não disponibiliza a ROM em seu site, eu mesmo precisei gerar estes arquivos.

Fiz um mapa mental com o esquema da imagem da ROM do Allwinner 10 para melhorar o entendimento:

O backup do sistema Android no tablet BC1003 é feito pela shell do dispositivo, que eu acesso com a linha de comando na shell do Linux:

adb shell

O adb é parte do Android Development Kit. Para descobrir quais são as partições do Android, já na shell do tablet, uso o seguinte comando para listar o diretório de dispositivos de bloco /dev/block:

ls /dev/block

Com isto, verifico que não há dispositivos com “mtd” no nome. Assim, o tablet não usa o subsistema mtd para gerenciar memória flash. Em vez disto, há partições com “nand”. Isto indica que a memória interna de 4 GB usa o esquema de partições eMMC e que as partições são:

  • nanda
  • nandb
  • nandc
  • nandd
  • nande
  • nandf
  • nandg
  • nandh
  • nandi

É um sistema Allwinner de 9 partições NAND. Este número é importante se eu escolher instalar alguma ROM Cyanogen, por exemplo, que possui versões para Allwinner de 9, 10 e 11 partições NAND.

Para descobrir o que há em cada partição, consulto o subsistema Linux /proc, que tem informações sobre  o dispositivo. Uso o comando “mount” ou:

cat /proc/mounts > /mnt/sdcard/mounts.txt

que gera um arquivo texto listando todas as partições montadas:

rootfs / rootfs ro,relatime 0 0
tmpfs /dev tmpfs rw,nosuid,relatime,mode=755 0 0
devpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,relatime 0 0
tmpfs /mnt/asec tmpfs rw,relatime,mode=755,gid=1000 0 0
tmpfs /mnt/obb tmpfs rw,relatime,mode=755,gid=1000 0 0
/dev/block/nandd /system ext4 ro,relatime,user_xattr,barrier=0,data=ordered 0 0
/dev/block/nande /data ext4 rw,nosuid,nodev,noatime,user_xattr,barrier=0,journal_checksum,data=ordered,noauto_da_alloc 0 0
/dev/block/nandh /cache ext4 rw,nosuid,nodev,noatime,user_xattr,barrier=0,journal_checksum,data=ordered,noauto_da_alloc 0 0
/dev/block/vold/179:2 /data/sdext2 vfat rw,relatime,uid=1000,gid=1000,fmask=0133,dmask=0002,allow_utime=0020,codepage=cp437,iocharset=ascii,shortname=mixed,errors=remount-ro 0 0
/dev/block/vold/93:64 /mnt/sdcard vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 0
/dev/block/vold/93:64 /mnt/secure/asec vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 0
tmpfs /mnt/sdcard/.android_secure tmpfs ro,relatime,size=0k,mode=000 0 0
/dev/block/dm-0 /mnt/asec/br.gov.caixa.webcaixa-1 vfat ro,dirsync,nosuid,nodev,relatime,uid=1000,fmask=0222,dmask=0222,codepage=cp437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 0
/dev/block/dm-1 /mnt/asec/com.antutu.CpuMasterFree-1 vfat ro,dirsync,nosuid,nodev,relatime,uid=1000,fmask=0222,dmask=0222,codepage=cp437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 0
/dev/block/dm-2 /mnt/asec/org.freeandroidtools.root_checker-1 vfat ro,dirsync,nosuid,nodev,relatime,uid=1000,fmask=0222,dmask=0222,codepage=cp437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 0
/dev/block/dm-3 /mnt/asec/com.apedroid.hwkeyboardhelperdemo-1 vfat ro,dirsync,nosuid,nodev,relatime,uid=1000,fmask=0222,dmask=0222,codepage=cp437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 0

Também posso olhar as mensagens do kernel com o comando:

cat /proc/kmsg

No início das mensagens, aos 2 segundos de boot, aparecem as linhas com os nomes das partições:

[ 2.219177] The 0 disk name = bootloader, class name = DISK, disk size = -419187676
[ 2.219191] The 1 disk name = env, class name = DISK, disk size = -419187612
[ 2.219203] The 2 disk name = boot, class name = DISK, disk size = -419187548
[ 2.219214] The 3 disk name = system, class name = DISK, disk size = -419187484
[ 2.219225] The 4 disk name = data, class name = DISK, disk size = -419187420
[ 2.219235] The 5 disk name = misc, class name = DISK, disk size = -419187356
[ 2.219246] The 6 disk name = recovery, class name = DISK, disk size = -419187292
[ 2.219257] The 7 disk name = cache, class name = DISK, disk size = -419187228
[ 2.219268] The 8 disk name = UDISK, class name = DISK, disk size = -419187164
[ 2.219279] The 8 disk size = 4917248

Mas o tamanho das partições é incompreensível. Para obter esta informação, uso o comando:

cat /proc/partitions > /mnt/sdcard/partitions.txt

que gera um texto com o tamanho real das partições (omiti algumas que não interessam agora):

major minor  #blocks  name
93       0      81920 nanda
93       8      16384 nandb
93      16      32768 nandc
93      24     524288 nandd
93      32     384000 nande
93      40      16384 nandf
93      48      32768 nandg
93      56     327680 nandh
93      64    2458624 nandi

A estrutura de partições do BC1003 é a seguinte:

Nome do dispositivo Tamanho Rótulo da partição Sistema de arquivo Comentários
0 nanda 80MB bootloader vfat Tabela de partições nos primeiros 16 MB e arquivos para assistir o bootloader nos outros 64 MB. Imagens do status da bateria, u-boot.bin, script.bin e .ini ficam aqui.
1 nandb 16MB env raw Ambiente para assistir o u-boot.
2 nandc 32MB boot raw Tem o kernel e seu ramdisk no formato ANDROID mkbootimg.
3 nandd 504MB system ext4 Partição /system do Android.
4 nande 375MB data ext4 Partição /data.
5 nandf 16MiB misc raw Partição usada para passar dados entre vários estágios da sequência de boot (por exemplo, boot no modo recovery, fastboot etc).
6 nandg 32MiB recovery raw Partição recovery com o kernel.
7 nandh 320MiB cache ext4 Partição montada como /cache.
8 nandi 2,401GB UBOOT vfat Partição montada como /mnt/sdcard.

As partições importantes são bootloader, env, boot, system e recovery. As outras são recriadas quando do primeiro boot e configuração.

Bootloader e environment

Dentro do shell do tablet, uso o comando dd para copiar as partições para o cartão MicroSD:

dd if=/dev/block/nanda of=/sdcard/bootloader.img
dd if=/dev/block/nandb of=/sdcard/env.img

O comando dd é mais informativo, mas também posso usar o comando cat:

cat /dev/block/nanda > /sdcard/bootloader.img

Depois de copiadas as partições para arquivos img no cartão MicroSD, pode-se conectar o cabo USB e copiá-los para o PC desktop, para manipulação. Também posso fazer isto do shell Linux ou Windows com o Android Debug Bridge (adb). Abaixo, os comandos estão juntos numa mesma linha para facilitar. A linha com o prompt “$” é o comando, as outras linhas são os resultados. A linha de comandos gera o backup, copia para o PC e apaga a imagem do cartão SD para liberar espaço. Primeiro, o bootloader:

$ adb shell dd if=/dev/block/nanda of=/sdcard/bootloader.img && adb pull /sdcard/bootloader.img && adb shell rm /sdcard/bootloader.img
163840+0 records in
163840+0 records out
83886080 bytes transferred in 19.563 secs (4287996 bytes/sec)

e, depois, o ambiente de boot:

adb shell dd if=/dev/block/nandb of=/sdcard/env.img && adb pull /sdcard/env.img && adb shell rm /sdcard/env.img
32768+0 records in
32768+0records out
16777216 bytes transferred in 1.507 secs (11132857 bytes/sec)

Bootloader

O bootloader é uma imagem no sistema de arquivo vfat e pode ser montada no Ubuntu com os comandos:

sudo mkdir /media/cranebootloader
sudo mount -t vfat -o loop bootloader.img /media/cranebootloader

Com isto, posso entrar no diretório /media/cranebootloader, investigar e extrair ou modificar arquivos desta imagem.

Yones default splash screen

Yones default splash screen

Na pasta /linux, por exemplo, estão muitas imagens em formato BMP que aparecem no boot (splash screen), como a imagem default de equipamento OEM, que é umas das mais feias que já vi. Para trocar por outra, se renomeia para “linux.bmp”. Várias destas imagens têm nomes de fabricantes — inclusive da Coréia do Norte–, o que me ajudou a achar as ROMs originais de um fabricante.

Também pode-se trocar a splash screen a partir do próprio Android shell. Entra-se no shell com o comando “adb shell” e usa-se os comandos abaixo:

mkdir /sdcard/nanda
mount -t vfat /dev/block/nanda /sdcard/nanda
cd /sdcard/nanda/linux
cp linux.bmp linux.old.bmp
cp seuarquivo.bmp linux.bmp

Env

O env é o ambiente para alguns parâmetros do boot. É um arquivo binário com strings terminadas em zero. Aberto por um editor hexadecimal, ele revela os seguintes parâmetros:

bootdelay=0
bootcmd=run setargs boot_normal
console=ttyS0,115200
nand_root=/dev/nandc
mmc_root=/dev/mmcblk0p4
init=/init
loglevel=8
setargs=setenv bootargs console=${console} root=${nand_root} init=${init} loglevel=${loglevel}
boot_normal=nand read 40007800 boot;boota 40007800
boot_recovery=nand read 40007800 recovery;boota 40007800
boot_fastboot=fastboot
recovery_key_value_max=0x13
recovery_key_value_min=0x10
fastboot_key_value_max=0x8
fastboot_key_value_min=0x2

Boot e recovery

As partições boot e recovery são copiadas com os comandos:

$ adb shell dd if=/dev/block/nandc of=/sdcard/boot.img && adb pull /sdcard/boot.img && adb shell rm /sdcard/boot.img
65536+0 records in
65536+0 records out
33554432 bytes transferred in 10.160 secs (3302601 bytes/sec)
5026 KB/s (33554432 bytes in 6.518s)
$ adb shell dd if=/dev/block/nandg of=/sdcard/recovery.img && adb pull /sdcard/recovery.img && adb shell rm /sdcard/recovery.img
65536+0 records in
65536+0 records out
33554432 bytes transferred in 6.065 secs (5532470 bytes/sec)
4850 KB/s (33554432 bytes in 6.755s

Elas estão num formato especial do Android, composto por um cabeçalho de 2kb, o kernel Linux e um ou dois ramdisks com arquivos básicos necessários para o boot. Para se trabalhar nestes arquivos — geralmente se modifica o ramdisk — deve-se separar os arquivos com utilitários desenvolvidos por hackers.

Estes arquivos têm a seguinte estrutura:

Área Nome Tamanho em bytes Formato Comentários
Header bootMagic 8 ASCII Identificador do tipo de estrutura do arquivo (“assinatura”). Contém “ANDROID!”
kernelSize 4 long int Tamanho do kernel em bytes
kernelLoadAddr 4 long int Endereço de carga do kernel na memória RAM do dispositivo
ram1Size 4 long int Tamanho do ramdisk 1 em bytes
ram1LoadAddr 4 long int Endereço da RAM onde carregar o ramdisk 1
ram2Size 4 long int Tamanho do ramdisk 2 em bytes
ram2LoadAddr 4 long int Endereço da RAM onde carregar o ramdisk 2
tagsAddr 4 long int Endereço de tags do kernel
pageSize 4 long int Tamanho das “páginas” do flash
unused1 4 long int Não usado
unused2 4 long int Não usado
bootName 16 ASCII Nome do system-on-chip (placa do hardware)
cmdLine 512 ASCII Linha de comando do kernel. Será usada mais tarde na recriação da imagem
id 6 ASCII Identificador (?)
Kernel kernel kernelSize binário Kernel Linux
RAM disk 1 ramdisk1 ram1Size binário Inicia com os bytes hexa 1F 8B (assinatura de ramdisk). Começa na página acima do kernel. Para calcular o tamanho do kernel em páginas, a fórmula é: kernelSizeInPages = (kernelSize + pageSize – 1) / pageSize. Para calcular o início do ramdisk, a fórmula é: ram1Addr = (1 + kernelSizeInPages) * pageSize
RAM disk 2 ramdisk2 ram2Size binário Raramente existe

O kernel e o ramdisk são extraído pelos scripts em Perl extract-kernel.pl e extract-ramdisk.pl, criados pelo hacker Lox:

extract-kernel.pl boot.img
extract-ramdisk.pl boot.img

O segundo script extrai e recria a estrutura de pastas do ramdisk, que está armazenada no formato cpio.gz.

Este trabalho também pode ser feito com um editor de arquivos binários como Bless Hex Editor.

initlogo.rle, segunda imagem do boot do BC1003

Por exemplo, dentro da pasta raiz existe o arquivo initlogo.rle, que é a segunda imagem que aparece depois que a gente liga o BC1003. É o androidezinho de braços cruzados copiado do site Android Central. Esta imagem está num formato raw (cru, sem cabeçalhos ou metainformações) que pode ser aberto pelo Irfanview, “File > Open as… > Raw file”, especificando-se tamanho 1024 x 600, 32 bits, ordem de cor ABGR, interleaved. Mas as cores vêm trocadas. Na verdade, ele é ARGB (Canal Alfa, Red, Green, Blue). Para ficar com as cores corretas, deve-se ir ao menu “Image > Swap colors > RGB -> BGR”. Descobri isto na tentativa e erro. O Irfanview não grava ARGB e não conheço programa para gravar neste formato, mas não deve ser difícil escrever um script — em Python, por exemplo — que converta o formato. Afinal, são apenas bytes crus.

System

A partição system contém todo o sistema Android. O backup, que é bem mais demorado que os anteriores — leva mais de 5 minutos — , é feito com o comando:

$ adb shell dd if=/dev/block/nandd of=/sdcard/system.img && adb pull /sdcard/system.img && adb shell rm /sdcard/system.img
1048576+0 records in
1048576+0 records out
536870912 bytes transferred in 149.046 secs (3602048 bytes/sec)
4738 KB/s (536870912 bytes in 110.635s)

A partição system está no formato ext4 sparse e deve ser convertida pelo programa simg2img (Linux) para ext4 normal, antes de ser montada pelo comando:

simg2img system.img system2.img
sudo mkdir /media/cranesystem
sudo mount -t ext4 -o loop system2.img /media/cranesystem

Depois de montadas, pode-se copiar a estrutura de arquivos para outro lugar e editá-los a gosto.

Recriando imagens

Feitas as mudanças, pode-se recriar as images do BC1003. O boot.img se recria assim, com os programas Linux mkboot:

# mkbootfs boot.img-ramdisk | gzip > ramdisk-boot 
# mkbooting --kernel boot.img-kernel --ramdisk ramdisk-boot --base 0x40000000 --cmdline 'console=ttyS0,115200 rw init=/init loglevel=6' -o new-boot.img

Através do shell, copia-se de volta as imagens para a partição correspondente, desde que o boot esteja intacto. Por exemplo, a imagem do sistema Android:

dd if=/sdcard/system.img of=/dev/block/nandd

O processo de criação de uma imagem completa da ROM allwinner, a partir de alguma ROM baixada de fabricantes, pode ser vista no site Allwinner/Alterning and Creating PhoenixSuit images. Com o programa Livesuite, da própria Allwinner, pode-se gravar todo o sistema no tablet, caso ele estrague.

Imagens prontas

Umas das marcas que comercializa este tablet é a Kocaso, dos EUA. É a única empresa em que eu achei as ROM do BC1003. A imagem que funcionou para meu BC1003 foi a primeira das três, arquivo M1050B.exe, de onde se extrai a imagem M1050_2.img.

Uma grata surpresa: elas têm uma partição /data com a triplo do tamanho desta da Wei: 1.048.576 bytes, em vez de 384.000 bytes. A partição /data é onde todos os programar guardam todo o tipo de dados e, em geral, é a primeira a ficar lotada, impedindo que se instalem novos programas, mesmo que a partição /system e o disco interno tenham espaço. No entanto, esta memória extra foi retirada do disco interno da Kocaso, em /mnt/sdcard ou /sdcard, que tem 1.810.432 bytes em vez de 2.458.624 bytes. Mas na prática, isto não é muito grave. A gente usa o aplicativo Link2SD e pode passar todos os programas novos para o cartão SD e deixar a memória de disco interna mais livre para música, filmes e fotos. Esta imagem da Kocaso não vem com o app GPS Test que vem no Wei Wide PRO mas basta baixá-lo e passá-lo para o diretório de sistema usando uma opção do Link2SD.

Este é o esquema de partições do Kocaso:

root@android:/ # cat /proc/partitions
cat /proc/partitions
major   minor    #blocks name
  93        0      65536 nanda [bootloader]
  93        8      16384 nandb
  93       16      32768 nandc
  93       24     524288 nandd [/system]
  93       32    1048576 nande [/data]
  93       40      16384 nandf
  93       48      32768 nandg [recovery]
  93       56     327680 nandh
  93       64    1810432 nandi [/sdcard]

Referências

Sobre José Antonio Meira da Rocha

Jornalista, professor de Planejamento Gráfico e Mídias Digitais da Universidade Federal de Santa Maria, campus da cidade de Frederico Westphalen, Rio Grande do Sul, Brasil. Doutorando em Design na UFRGS, Porto Alegre, Brasil, 2014.