Table of Contents
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
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
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
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.
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.
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.