Como Extrair e Decompilar a Device Tree de um Dispositivo Android
Neste tutorial, você aprenderá como extrair e decompilar a Device Tree de um dispositivo Android. Passaremos por todo o processo, desde a extração do boot.img até a identificação do arquivo correto da
Introdução
A Device Tree (ou Árvore de Dispositivos) é uma estrutura de dados fundamental que descreve os componentes de hardware de um dispositivo Android. la permite que o kernel do sistema operacional saiba como interagir com o hardware, como processadores, memória, interfaces de rede, e outros periféricos conectados ao dispositivo.
Ela geralmente é encontrada dentro do boot.img no formato compilado (DTB).
DTS = Device Tree Source (código-fonte)
DTB = Device Tree Blob (versão compilada, usada pelo kernel)
Dispositivos
Neste tutorial, utilizarei o smartphone LG L70 (codename lg-w5), rodando Android 4.4.2 com o kernel versão 3.4.0. Os procedimentos serão executados nos sistemas operacionais Debian 12 e Windows 11.
Como obter o boot.img
Se você já possui o arquivo boot.img, pode seguir diretamente para “Extraindo a Device Tree (DTB) do boot.img”.
O primeiro passo para extrair a Device Tree do dispositivo é obter o boot.img. Esse arquivo contém o kernel, o Ramdisk (initramfs ou initrd), e uma série de arquivos de configuração. É dentro do boot.img que também se encontra o arquivo da Device Tree do dispositivo, essencial para as etapas seguintes.
1. Extração do boot.img da ROM
As ROMs, especialmente as stock ROMs (as que vêm de fábrica nos smartphones), podem ter formatos de compactação variados. Para extrair os arquivos, incluindo o boot.img, será necessário utilizar uma ferramenta específica para descompactação. Sugiro que pesquise por termos como “como extrair + formato da sua ROM”; você provavelmente encontrará tutoriais e ferramentas úteis no xda-forums.com.
Observe que a stock ROM que estou utilizando está compactada no formato .kdz, que é um padrão adotado pela LG e compatível com ferramentas como o LG Flash Tool.
Para descompactar a ROM, usarei a ferramenta KDZTools (link para o GitHub), que é específica para descompactar ROMs da LG no formato .kdz. Utilizarei os binários (.exe) do KDZTools disponibilizados no XDA.
Passo a Passo para Extrair o boot.img utilizando KDZTools
Coloque o arquivo da sua ROM .kdz dentro da pasta do KDZTools.
Execute o script “OneKeyExtraction.bat”.
Se tudo ocorrer corretamente, será criada uma pasta com o nome do arquivo .kdz, acrescido de “_img”. No meu caso, foi criada a pasta D325f810d_00_img.
Dentro dessa pasta, você encontrará vários arquivos .img, incluindo o arquivo necessário: boot.img.
Lembre-se de que a compressão de ROMs pode variar conforme o fabricante ou a versão do Android. Por isso, é fundamental utilizar a ferramenta certa para descompactar a ROM corretamente.
2. Extração do boot.img pelo ADB
Se o seu dispositivo estiver enraizado (rooted) e com o ADB (Android Debug Bridge) ativado, você pode extrair o boot.img diretamente pela shell ou até mesmo por meio de um aplicativo de terminal.
Para começar, acesse a shell do seu dispositivo utilizando o seguinte comando:
adb shell
Em seguida, precisamos localizar a partição onde o boot.img está armazenado. Para isso, vamos listar as partições montadas no dispositivo com o seguinte comando na shell:
ls -l /dev/block/platform/msm_sdcc.1/by-name/
Esse comando irá retornar uma lista de partições, e você deve procurar pela partição que contém o boot. O resultado será algo semelhante à imagem abaixo:
Observe na imagem que podemos identificar a referência para a partição do boot:
boot -> /dev/block/mmcblk0p16
Agora sabemos que a partição boot do nosso dispositivo está localizada em /dev/block/mmcblk0p16.
O próximo passo é copiar os dados da partição utilizando o comando DD da seguinte maneira:
dd if=/dev/block/mmcblk0p16 of=/mnt/sdcard/boot.img bs=4M
Aqui, em if especificamos o caminho da partição (input file), e em of o destino onde queremos salvar a imagem, neste caso /mnt/sdcard/boot.img. O parâmetro bs=4M define o tamanho do bloco de dados a ser transferido.
Aguarde até que o procedimento seja concluído. Durante esse tempo, pode ser que não apareça nenhuma saída no terminal. Não se preocupe, apenas continue aguardando até que o prompt de comando apareça novamente, indicando que o processo foi finalizado e você pode digitar novos comandos.
Se tudo correr bem, o boot.img será extraído diretamente do seu smartphone. Agora, basta transferir o arquivo para o seu computador e seguir com os passos do próximo capítulo.
3. Extração do boot.img pelo TWRP
Se você tiver o TWRP (ou outro recovery customizado semelhante) instalado, pode realizar o backup da partição boot diretamente pelo recovery do seu smartphone. Este método é mais simples e direto. No TWRP, basta ir até a opção "Backup", selecionar a partição "boot", e o arquivo será salvo no diretório padrão do TWRP, na raiz da memória interna ou no SDCard, dependendo da sua configuração.
Extraindo a Device Tree do boot.img
Agora que temos o arquivo boot.img, precisaremos de uma ferramenta chamada unpackbootimg (link para o repositório). Essa ferramenta serve para descompactar o boot.img, extraindo o arquivo da Device Tree, que será decompilado, além de outros arquivos importantes.
Primeiro, você precisa clonar o repositório ou baixar os arquivos e compilar o unpackbootimg. Supondo que você já tenha feito a compilação, o próximo passo é executar o seguinte comando no diretório onde o unpackbootimg e o boot.img estão localizados (você pode criar um diretório específico ou colocar ambos os arquivos em um único diretório):
./unpackbootimg -i boot.img
Após a execução, procure por um arquivo com nome semelhante a boot.img-dtb. Esse é o arquivo da Device Tree Blob (DTB). O próximo passo é identificar o tipo desse arquivo e, se necessário, decompilá-lo ou extrair as diferentes árvores (caso haja mais de uma) para decompilar as Device Trees Blobs (DTB) extraídas.
Decompilando a Device Tree Blob (DTB)
Na etapa anterior obtivemos o arquivo boot.img-dtb, agora precisamos decompilar esse arquivo para obter a Device Tree Source (DTS), que é o código-fonte da nossa Device Tree.
O primeiro passo é tentar utilizar o dtc (device tree compiler) para decompilar a Device Tree Blob (DTB), antes, talvez seja preciso instala-lo:
sudo apt-get install device-tree-compiler
Após isso podemos utilizar o seguinte comando para tentar decompilar:
dtc -I dtb -O dts -o output.dts boot.img-dtb
-I dtb: Informa ao dtc que o arquivo de entrada é um arquivo dtb.
-O dts: Informa ao dtc que o arquivo de saída será um arquivo dts.
-o output.dts: Especifica o nome do arquivo de saída (output.dts).
Se tudo ocorrer corretamente, você deverá obter o arquivo DTS. No meu caso, porém, encontrei o seguinte erro ao tentar decompilar:
$ dtc -I dtb -O dts -o output.dts boot.img-dtb
FATAL ERROR: Blob has incorrect magic number
Esse erro indica que o arquivo boot.img-dtb não está em um formato válido para ser decompilado diretamente pelo dtc. Isso pode ocorrer por dois motivos principais: ou o arquivo não é um DTB válido, ou ele está embutido em outro formato.
Para investigar o problema, podemos examinar o cabeçalho do arquivo usando ferramentas como o xxd ou HexDump:
xxd boot.img-dtb | head -n 10
No meu caso, o arquivo boot.img-dtb na verdade estava no formato QCDT, que começa com a sequência de bytes 5143 4454.
De acordo com a Wiki do PostMarketOS, os dispositivos Qualcomm também utilizam o formato QCDT, onde o DTB é anexado ao final do sistema de arquivos (boot.img), ao invés de ser incluído no zImage. Mais detalhes podem ser encontrados aqui.
Agora, para extrair os DTB do arquivo QCDT (boot.img-dtb), usarei a ferramenta Binwalk, versão mais recente (v 3.1.0), instalada via Rust package manager.
Instalação do Binwalk
Primeiro, instale o cargo (gerenciador de pacotes do Rust) e dependência:
sudo apt install cargo build-essential libfontconfig1-dev liblzma-dev
Em seguida, instale o binwalk com o seguinte comando:
cargo install binwalk
Após a instalação, adicione o binwalk ao PATH:
export PATH="$HOME/.cargo/bin:$PATH"
Analisando boot.img-dtb com Binwalk
Com o binwalk em mãos, vamos agora analisar o nosso arquivo QCDT (boot.img-dtb):
binwalk boot.img-dtb
O binwalk identificou dois blobs de árvore de dispositivos (DTB), começando em dois pontos diferentes (offsets 0x800 e 0x27800), com um tamanho total de cerca de 158.869 bytes e 158.706 bytes, respectivamente.
Você pode extrair os dois DTB encontrados de maneira simples utilizando o Binwalk:
binwalk -e boot.img-dtb
Esse comando irá extrair ambos os DTB na pasta onde o comando foi executado.
Alternativamente, você pode usar o DD para extrair os arquivos manualmente:
dd if=boot.img-dtb of=dtb1.dtb bs=1 skip=2048 count=158869
dd if=boot.img-dtb of=dtb2.dtb bs=1 skip=161792 count=158706
Com isso, finalmente obtemos os arquivos DTB (dtb1.dtb e dtb2.dtb), que podem ser decompilados usando o DTC:
dtc -I dtb -O dts -o dtb1.dts dtb1.dtb
dtc -I dtb -O dts -o dtb2.dts dtb2.dtb
Agora, temos os arquivos decompilados: dtb1.dts e dtb2.dts prontos para análise.
Como Identificar Qual Device Tree Pertence ao Seu Dispositivo
Agora que temos os arquivos DTS, o próximo passo é identificar qual deles corresponde ao nosso dispositivo. É comum encontrar várias Device Trees dentro do boot.img, então o desafio agora é descobrir qual delas deve ser usada.
No meu caso, como tenho apenas duas Device Trees, utilizei o comando diff para comparar as duas e percebi apenas três diferenças. A principal delas está relacionada à versão do processador.
Exemplo de comparação:
dtb1.dts:
/dts-v1/;
/ {
#address-cells = <0x01>;
#size-cells = <0x01>;
model = "Qualcomm MSM 8610v1 w5dsopenbr";
compatible = "qcom,msm8610-w5dsopenbr\0qcom,msm8610";
interrupt-parent = <0x01>;
qcom,msm-id = <0x93 0x00 0xa5 0x00 0xa1 0x00 0xa2 0x00 0xa3 0x00 0xa4 0x00 0xa6 0x00>;
qcom,board-id = <0x7a 0x00>;
dtb2.dts:
/dts-v1/;
/ {
#address-cells = <0x01>;
#size-cells = <0x01>;
model = "Qualcomm MSM 8610v2 w5dsopenbr";
compatible = "qcom,msm8610-w5dsopenbr\0qcom,msm8610";
interrupt-parent = <0x01>;
qcom,msm-id = <0x93 0x10001 0xa5 0x10001 0xa1 0x10001 0xa2 0x10001 0xa3 0x10001 0xa4 0x10001 0xa6 0x10001>;
qcom,board-id = <0x7a 0x00>;
Basicamente, a única diferença entre as duas Device Trees está na versão do Qualcomm MSM 8610. A dtb1.dts é para a versão 1, enquanto a dtb2.dts é para a versão 2, com pequenas modificações, como a adição de dois dispositivos no MSM8610v2.
Verificando a Device Tree no Sistema
Você pode tentar identificar a Device Tree do seu dispositivo verificando os seguintes caminhos no sistema:
/proc/device-tree/qcom,board-id
/proc/device-tree/qcom,msm-id
Se, como no meu caso, você não encontrar a pasta /proc/device-tree, pode tentar buscar informações nos logs do sistema, como dmesg, logcat, getprop, entre outros, procurando por msm-id, board-id, model, etc.