Android: How to Unpack/Pack Factory Images 11


A typical Android factory package contains several image files, such as system.img, cache.img, userdata.img, boot.img, recovery.img, etc. Although all these files contains the “img” in their names, they are not all of the same format.

According to my experience, there are two file format for these files.

boot.img and recovery.img

Unpack

These files are packed to a Android boot image format, if you use file command to see their type, the command will tell you that it is a data file.

file boot.img
# boot.img: data

if you use inspect into the file’s content, you will see “ANDROID” in the very beginning.

head -n 1 recovery.img
# ANDROID!H�=�a��Y(6�����G�GB��XH�=KERNEL

How to unpack these files? If you are using Ubuntu(or other Linux distributions, I believe), there is a handy tool: abootimg, it can create or extract such kind of images for you. Simply type the following command to install:

sudo apt-get install abootimg

Now you have abootimg installed in your system, you can easily extract boot.img:

mkdir boot
cd boot
abootimg -x ../boot.img
# after the successful execution of the last command, we will have initrd.img, zImage, etc.
# inside the boot folder.

Sometimes we need to change the init ramfs(packed in initrd.img), then we need to unpack the initrd.img. First of all, we need to make sure the initrd.img(some vendor might add a wrapper header to the original image):

file initrd.img
# the output should be similar to the following line:
# initrd.img: gzip compressed data, from Unix

Now we know the initrd.img is a gzip file, we can unpack it use gunzip(gzip -d) combined with cpio:

mkdir ramdisk
cd ramdisk
# "gunzip -c ../initrd.img" means unpack to standard output
gunzip -c ../initrd.img | cpio -i

That’ all, you can dig into the ramdisk folder now^_^.

Oh, forgot to tell you, the “abootimg-unpack-initrd” along with abootimg package do the same thing for you and can save you from typing a lot of command^)^.

abootimg-unpack-initrd initrd.img
# this command will create a ramdisk folder automatically and
# unpack the image to the ramdisk folder

Pack

  • initrd.img

    To reverse the unpack action, abootimg package provides another command named “abootimg-pack-initrd”, here is its usage:

    abootimg-pack-initrd [-f] [initrdimg_path] [ramdisk_folder_path]
    # -f: force write. if you would like to use this flag, make sure to place it as the first argument
    # initrdig_path: the path of the target initrd.img file
    # ramdisk_folder_path: the ramdisk folder path
    
  • boot.img/recovery.img

    To generate a boot.img or recovery.img, again, we need the abootimg tool.

    # to create an image:
    abootimg --create <bootimg> [-c "param=value"] [-f <bootimg.cfg>] -k <kernel> -r <ramdisk> [-s <secondstage>]
    
    # to update an existing image:
    abootimg -u <bootimg> [-c "param=value"] [-f <bootimg.cfg>] [-k <kernel>] [-r <ramdisk>] [-s <secondstage>]
    
    # Note: the option "-r <ramdisk>", where ramdisk is initrd.img, not the ramdisk folder.
    

system.img, userdata.img, cache.img, etc.

Unpack

Distinguish from boot image, images such as system.img is called user image in Android. Early version of Android(previous to Android 2.3 Gingerbread) use yaffs2 as its filesystem, and use ext4 as it filesystem from Gingerbread(read this post to get some detail about the switch: Ext4 filesystem hits Android, no need to fear data loss).

To decide what format is your image, we can make use of the “file” command:

file system.img
# if the iamge is a yaffs2 image, the output might look like:
# system.img: VMS Alpha Exectutable

# if the image is a ext4 image, the output might be:
# system.img: data

If your image is a yaffs2 image, you can use the yaffs2utils tools to unpack or pack the image. I won’t dig into the detail of yaffs2 image because I have very limited experience on it.

Now you have a system.img that its type is “data”, how can you know whether it is a ext4 image? Android provide a tool named simg2img(which means: sparse image to image) to do the job. We can get the source code of simg2img in the AOSP(Android OpenSource Project), inside the system/extras/ext4_utils/ folder. Read this for an instruction to compile it without compiling the whole AOSP: How to pack and unpack system.img and userdata.img from an Android factory image.

Once you have simg2img installed, you can simply type this command in the terminal:

simg2img system.img system.ext4.img

If the command didn’t yield any error, congratulation! Double check with the “file” command:

file system.ext4.img
# should output something like:
# system.ext4.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-0000-675f-946fc0f9f25b (extents) (large files)

Mount the image using this:

sudo mount -t ext4 -o loop system.ext4.img /mnt
# make sure you have the privilege(sudo or root) to mount the image

Do whatever you want to the files under /mnt(the mount point), and all your modification will be saved when you umount the image.

Pack

When we done with the modifications, we may want to repack the system image(note I won’t touch the topic that how to create a yaffs2 image here). In that case, we need another tools: make_ext4fs and mkuserimg.sh, the source code of these tools also in system/extra/ext4_utils/, you can follow the instructions in How to pack and unpack system.img and userdata.img from an Android factory image to compile the make_ext4fs. The mkuserimg.sh is a wrapper program that it will call make_ext4fs eventually.

mkuserimg.sh
# Usage:
# mkuserimg.sh [-s] SRC_DIR OUTPUT_FILE EXT_VARIANT MOUNT_POINT SIZE

# Example:
sudo mkuserimg.sh -s system/ system.img ext4 /system 500m
# ths "-s" flag indicates that we want to generate a sparse image, otherwise it will gengerate
# am image that we can mount it directly without using simg2img.

# the first "system/" is the system folder(for example, the mount point of the system.ext4.img)
# the second "/system" specify the mount point inside Andriod system.
# the last argument(500m) specify the image size. when mounted in the target Android system, the
# actual partition size would be 10m(approximately) less than this size. the image size must
# conform to the partition size defined in MBR or EBR, or some image data might be overrided by
# subsequent image.

Author: Rex Shen

Created: 2014-09-24 Wed 14:06

Emacs 24.3.1 (Org mode 8.2.7c)

Validate


Leave a comment

Your email address will not be published. Required fields are marked *

11 thoughts on “Android: How to Unpack/Pack Factory Images

  • Viranjan

    Nice article to understand about boot.img , system.img etc.
    Can you please add some knowledge about vendor.img and cache.img as well. There is just a mention of it.

    Thanks.

    • Rex
      Rex Post author

      Viranjan,
      vendor specific files usually reside in /system/vendor, rather than a stand alone partition. Anyway, if there is a vendor.img, the file structure inside the partition may be similar to system.img.

      cache.img usually an empty image(with only filesystem data). Android use such empty images to initialise the partitions, so Android do not to call mkfs.ext4 to format such partitions. Some usage of the /cache partition are:
      1) when we download from GooglePlay, the files are stored in /cache temporarily
      2) the downloaded ota package(update.zip) is saved in /cache
      3) when doing an ota update, the log files that are generated by recovery are saved in /cache/recovery
      4) store some backup data

  • Aamir

    how do i unmount that mnt folder after modificatoin. plz help
    and other problem is that my system says about mkuserimg.sh that command not found. help plz i m waiting

    • Rex
      Rex Post author

      Aamir,
      1) to unmount, you can simply run this command: “sudo umount /mnt”. note that the command is “umount” rather than “unmount”
      2) you can get a copy of mkuserimg.sh from the Android’s source code: system/extra/ext4_utils/

  • Johannes Schenk

    Thanks for the guide!

    Unfortunately, if I unpack my boot.img with “abootimg -x”, repackage with “abootimg –create” and then flash with mfastboot my device doesn’t boot anymore, even if I’ve made absolutely no changes. I have a Moto G.

    Any idea what could be the problem?

    Thanks!

  • Tony

    Excelent!!

    Now you can install these android tools in Ubuntu typing:

    sudo apt-get install android-tools-fsutils

    It will install, simg2img, mkuserimg.sh and others

  • Lucky Patcher

    If you do not not know how to extract system.img file or derive system dump of Android devices, our today s tutorial is just for you. We tested this method on a system.img file from a Nexus 5 factory image package.

  • Vladimir

    For MTK based devices we should use tools like
    https://github.com/bgcngm/mtk-tools
    of Bruno Martins. Only his simple perl script helps me. It seems MTK used own format for boot.img and recovery.img. Unfortunately, abootimg can’t extract cpio initrd file in this case. But extracted images of kernels looks the same (diff say that)