How to Extract and Decompile the Device Tree from an Android Device
In this tutorial, you'll learn how to extract and decompile the Device Tree from an Android device, covering everything from extracting boot.img to identifying the correct Device Tree file.
Introduction
A Device Tree is a crucial data structure that describes the hardware components of an Android device. It allows the operating system kernel to understand how to interact with the hardware, such as processors, memory, network interfaces, I/O inputs, and other peripherals connected to the device.
It is usually found within the boot.img in a compiled format (DTB).
DTS = Device Tree Source (uncompiled version)
DTB = Device Tree Blob (compiled version, used by the kernel)
Devices
In this tutorial, I will be using the LG L70 smartphone (codename lg-w5), running Android 4.4.2 with kernel version 3.4.0. The procedures will be performed on Debian 12 and Windows 11 operating systems.
How to Obtain the boot.img
If you already have the boot.img file, you can jump directly to "Extracting the Device Tree (DTB) from boot.img"
The first step in extracting the Device Tree from the device is to obtain the boot.img. This file contains the kernel, the Ramdisk (initramfs or initrd), and a variety of configuration files. It is inside the boot.img that the device's Device Tree (DTB) file can also be found, which is essential for the following steps.
1/3. Extracting the boot.img from the ROM
ROMs, especially stock ROMs (those that come pre-installed on smartphones), can have various compression formats. To extract the files, including boot.img, you will need a specific tool for decompression. I suggest searching for terms like "how to extract + your ROM format"; you will likely find useful tutorials and tools on xda-forums.com.
Note that the stock ROM I am using is compressed in the .kdz format, which is a standard adopted by LG and compatible with tools such as the LG Flash Tool.
To decompress the ROM, I will be using the KDZ Tools, which is specifically for decompressing LG ROMs in .kdz format. I will use the KDZ Tools binaries (.exe) provided on XDA.
Step-by-Step to Extract boot.img using KDZTools
Place the .kdz ROM file inside the KDZTools folder.
Run the "OneKeyExtraction.bat" script.
If everything goes correctly, a folder will be created with the name of the .kdz file, appended with "_img". In my case, the folder D325f810d_00_img was created.
Inside this folder, you will find several .img files, including the necessary one: boot.img.
Remember that ROM compression may vary depending on the manufacturer or Android version. Therefore, it is essential to use the correct tool to properly extract the ROM.
2/3. Extracting boot.img via ADB
If your device is rooted and ADB (Android Debug Bridge) is enabled, you can extract the boot.img directly through the shell or even by using a terminal app.
To begin, access the device shell using the following command:
adb shell
Next, we need to locate the partition where the boot.img is stored. To do this, let's list the mounted partitions on the device with the following command in the shell:
ls -l /dev/block/platform/msm_sdcc.1/by-name/
This command will return a list of partitions, and you should look for the partition containing the boot. The result will look similar to the image below:
Note that we can identify the reference to the boot partition:
Now we know that the boot partition on our device is located at /dev/block/mmcblk0p16.
The next step is to copy the partition data using the DD command as follows:
dd if=/dev/block/mmcblk0p16 of=/mnt/sdcard/boot.img bs=4M
Here, "if" specifies the partition path (input file), and "of" is the destination where we want to save the image, in this case, /mnt/sdcard/boot.img. The parameter "bs=4M" defines the block size for data transfer.
Wait until the process is completed. During this time, no output may appear in the terminal. Don't worry, just wait until the command prompt reappears, indicating that the process has finished and you can enter new commands.
If everything went well, the boot.img will be extracted directly from your smartphone. Now, just transfer the file to your computer and proceed with the steps in the next chapter.
3/3. Extracting boot.img via TWRP
If you have TWRP (or another similar custom recovery) installed, you can back up the boot partition directly from your smartphone’s recovery. This method is simpler and more direct. In TWRP, just go to the "Backup" option, select the "boot" partition, and the file will be saved in the default TWRP directory, either in the internal storage or on the SDCard, depending on your configuration.
Extracting the Device Tree (DTB) from boot.img
Now that we have the boot.img file, we will need a tool called unpackbootimg (link to the repository). This tool is used to unpack the boot.img and extract the Device Tree Blob (DTB) file, which will be decompiled along with other important files.
First, you need to clone the repository or download the files and compile unpackbootimg.
Assuming you've already compiled it, the next step is to run the following command in the directory where unpackbootimg and boot.img are located (you can create a specific directory or put both files in one folder):
./unpackbootimg -i boot.img
After execution, look for a file with a name similar to boot.img-dtb. This is the Device Tree Blob (DTB) file. The next step is to identify the type of this file and, if necessary, decompile it or extract the different trees (if there are more than one) to decompile the extracted Device Trees Blob (DTB).
Decompiling the Device Tree Blob (DTB)
In the previous step, we obtained the boot.img-dtb file, and now we need to decompile this file to get the Device Tree Source (DTS), which is the source code of our Device Tree.
The first step is to try using the dtc (device tree compiler) to decompile the Device Tree Blob (DTB), but before doing that, you may need to install it:
sudo apt-get install device-tree-compiler
After installation, we can use the following command to attempt decompilation:
dtc -I dtb -O dts -o output.dts boot.img-dtb
-I dtb: Specifies that the input file is a dtb file.
-O dts: Specifies that the output will be a dts file.
-o output.dts: Specifies the name of the output file (output.dts).
If everything goes well, you should obtain the DTS file. In my case, however, I encountered the following error when trying to decompile:
$ dtc -I dtb -O dts -o output.dts boot.img-dtb
FATAL ERROR: Blob has incorrect magic number
This error indicates that the boot.img-dtb file is not in a valid format to be directly decompiled by dtc. This can happen for two main reasons: either the file is not a valid DTB, or it is embedded in another format.
To investigate the issue, we can examine the file header using tools like xxd or HexDump:
xxd boot.img-dtb | head -n 10
In my case, the boot.img-dtb file was actually in QCDT format, which starts with the byte sequence 5143 4454.
According to the PostMarketOS Wiki, Qualcomm devices also use the QCDT format, where the DTB is appended to the end of the filesystem (boot.img), rather than being included in the zImage. More details can be found here.
Now, to extract the DTB from the QCDT file (boot.img-dtb), I will use the Binwalk tool, version 3.1.0, installed via the Rust package manager.
Installing Binwalk
First, install cargo (the Rust package manager):
sudo apt install cargo
Then, install binwalk with the following command:
cargo install binwalk
After installation, add binwalk to your PATH:
export PATH="$HOME/.cargo/bin:$PATH"
Analyzing boot.img-dtb with Binwalk
With binwalk in hand, let's now analyze our QCDT file (boot.img-dtb):
binwalk boot.img-dtb
Binwalk identified two device tree blobs (DTBs), starting at two different offsets (0x800 and 0x27800), with a total size of approximately 158,869 bytes and 158,706 bytes, respectively.
You can extract the two DTBs found easily using Binwalk:
binwalk -e boot.img-dtb
This command will extract both DTBs in the directory where the command was executed.
Alternatively, you can use DD to manually extract the files:
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
With this, we finally obtain the DTB files (dtb1.dtb and dtb2.dtb), which can be decompiled using DTC:
Now, we have the decompiled files: dtb1.dts and dtb2.dts, ready for analysis.
Identifying Which Device Tree Belongs to Your Device
Now that we have the DTS files, the next step is to identify which one corresponds to our device. It's common to find multiple Device Trees within boot.img, so the challenge now is to figure out which one to use.
In my case, since I only have two Device Trees, I used the diff command to compare the two and found only three differences. The main one relates to the processor version.
Example comparison:
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>;
Basically, the only difference between the two Device Trees is the Qualcomm MSM 8610 version. The dtb1.dts is for version 1, while dtb2.dts is for version 2, with small modifications, like the addition of two devices in MSM8610v2.
Checking the Device Tree on the System
You can try to identify the Device Tree of your device by checking the following paths in the system:
/proc/device-tree/qcom,board-id
/proc/device-tree/qcom,msm-id
If, like in my case, you can't find the /proc/device-tree folder, you can try searching for information in the system logs, such as dmesg, logcat, getprop, among others, looking for msm-id, board-id, model, etc.