makefile
build\core\makefile
#$(1): output file
define build-systemimage-target
@echo "Target system fs image: $(1)"
$(call create-system-vendor-symlink)
@mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt
$(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, \
skip_fsck=true)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
./build/tools/releasetools/build_image.py \
$(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) $(TARGET_OUT) \
|| ( echo "Out of space? the tree size of $(TARGET_OUT) is (MB): " 1>&2 ;\
du -sm $(TARGET_OUT) 1>&2;\
if [ "$(INTERNAL_USERIMAGES_EXT_VARIANT)" == "ext4" ]; then \
maxsize=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE); \
if [ "$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" == "true" ]; then \
maxsize=$$((maxsize - 4096 * 4096)); \
fi; \
echo "The max is $$(( maxsize / 1048576 )) MB." 1>&2 ;\
else \
echo "The max is $$(( $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) / 1048576 )) MB." 1>&2 ;\
fi; \
mkdir -p $(DIST_DIR); cp $(INSTALLED_FILES_FILE) $(DIST_DIR)/installed-files-rescued.txt; \
exit 1 )
endef
$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
$(call build-systemimage-target,$@)
这里调用build-systemimage-target,参数为$(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
INSTALLED_SYSTEMIMAGE := $(PRODUCT_OUT)/system.img
SYSTEMIMAGE_SOURCE_DIR := $(TARGET_OUT)
生成system.img调用build-systemimage-target函数,build-systemimage-target函数调用generate-userimage-prop-dictionary生成$(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt ,最终调用./build/tools/releasetools/build_image.py脚本。
generate-userimage-prop-dictionary
#KaTeX parse error: Expected 'EOF', got '#' at position 45: …ictionary file #̲(2): additional “key=value” pairs to append to the dictionary file.
define generate-userimage-prop-dictionary
$(if $(INTERNAL_USERIMAGES_EXT_VARIANT),$(hide) echo "fs_type=$(INTERNAL_USERIMAGES_EXT_VARIANT)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_PARTITION_SIZE),$(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_fs_type=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_JOURNAL_SIZE),$(hide) echo "system_journal_size=$(BOARD_SYSTEMIMAGE_JOURNAL_SIZE)" >> $(1))
$(if $(BOARD_HAS_EXT4_RESERVED_BLOCKS),$(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_squashfs_compressor=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
$(if $(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "userdata_fs_type=$(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
$(if $(BOARD_USERDATAIMAGE_PARTITION_SIZE),$(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "cache_fs_type=$(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
$(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1))
#add for OTA
$(if $(BOARD_KERNELIMAGE_PARTITION_SIZE),$(hide) echo "kernel_size=$(BOARD_KERNELIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_UBOOTIMAGE_PARTITION_SIZE),$(hide) echo "mmcblk0boot0_size=$(BOARD_UBOOTIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_BOOTIMAGE_PARTITION_SIZE),$(hide) echo "ramdisk_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_MODEMARM_IMAGE_PARTITION_SIZE),$(hide) echo "modemarm_size=$(BOARD_MODEMARM_IMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_MODEMDISPI0_IMAGE_PARTITION_SIZE),$(hide) echo "modemdsp_size=$(BOARD_MODEMDISPI0_IMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_RECOVERYIMAGE_PARTITION_SIZE),$(hide) echo "ramdisk_recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_LCBOOTIMAGE_PARTITION_SIZE),$(hide) echo "lcboot_size=$(BOARD_LCBOOTIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_FDT_PARTITION_SIZE),$(hide) echo "dtb_size=$(BOARD_FDT_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_BL2_PARTITION_SIZE),$(hide) echo "bootstrap_size=$(BOARD_BL2_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_BL31_PARTITION_SIZE),$(hide) echo "secure_monitor_size=$(BOARD_BL31_PARTITION_SIZE)" >> $(1))
#end add for OTA
$(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_fs_type=$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_PARTITION_SIZE),$(hide) echo "vendor_size=$(BOARD_VENDORIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_JOURNAL_SIZE),$(hide) echo "vendor_journal_size=$(BOARD_VENDORIMAGE_JOURNAL_SIZE)" >> $(1))
$(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_OEMIMAGE_JOURNAL_SIZE),$(hide) echo "oem_journal_size=$(BOARD_OEMIMAGE_JOURNAL_SIZE)" >> $(1))
$(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1))
$(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(1)
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER),$(hide) echo "boot_signer=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(VERITY_SIGNER)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(FUTILITY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
$(if $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)),\
$(hide) echo "system_root_image=true" >> $(1);\
echo "ramdisk_dir=$(TARGET_ROOT_OUT)" >> $(1))
$(if $(2),$(hide) $(foreach kv,$(2),echo "$(kv)" >> $(1);))
endef
$(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1))
会把各个参数写的system_image_info.txt
其中extfs_sparse_flag=-s
INTERNAL_USERIMAGES_SPARSE_EXT_FLAG在makefile中
ifneq (true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED))
INTERNAL_USERIMAGES_SPARSE_EXT_FLAG := -s
endif
默认没有TARGET_USERIMAGES_SPARSE_EXT_DISABLED,
说以默认INTERNAL_USERIMAGES_SPARSE_EXT_FLAG := -s
表示生成的system.img为SPARSE格式
build_image.py
./build/tools/releasetools/build_image.py
$(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1)
调用build_image.py参数为out product目录,system_image_info.txt,目标文件system.img
def main(argv):
if len(argv) != 4:
print __doc__
sys.exit(1)
in_dir = argv[0]
glob_dict_file = argv[1]
out_file = argv[2]
target_out = argv[3]
glob_dict = LoadGlobalDict(glob_dict_file)这个函数添加system_image_info.txt内容添加到全局属性字典中
if "mount_point" in glob_dict:
# The caller knows the mount point and provides a dictionay needed by
# BuildImage().
image_properties = glob_dict
else:
image_filename = os.path.basename(out_file)
mount_point = ""
if image_filename == "system.img":
mount_point = "system"
elif image_filename == "userdata.img":
mount_point = "data"
elif image_filename == "cache.img":
mount_point = "cache"
elif image_filename == "vendor.img":
mount_point = "vendor"
elif image_filename == "oem.img":
mount_point = "oem"
else:
print >> sys.stderr, "error: unknown image file name ", image_filename
exit(1)
image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
if not BuildImage(in_dir, image_properties, out_file, target_out):
print >> sys.stderr, "error: failed to build %s from %s" % (out_file,
in_dir)
exit(1)
设置全局属性词典,调用BuildImage
BuildImage中,
build_command = [“mkuserimg.sh”]
RunCommand(build_command)
调用了system\extras\ext4_utils\mkuserimg.sh
mkuserimg.sh
mkuserimg.sh
调用
MAKE_EXT4FS_CMD="make_ext4fs $ENABLE_SPARSE_IMAGE -T $TIMESTAMP $OPT -l $SIZE $JOURNAL_FLAGS -a $MOUNT_POINT $OUTPUT_FILE $SRC_DIR $PRODUCT_OUT"
echo $MAKE_EXT4FS_CMD
$MAKE_EXT4FS_CMD
其中 -s为
ENABLE_SPARSE_IMAGE=
if [ "$1" = "-s" ]; then
ENABLE_SPARSE_IMAGE="-s"
shift
fi
所以make_ext4fs中带有-s参数
举例:make_ext4fs -s -l 3141572800 -a root system.img system
生成的system.img为android格式的img
sparse ext4 image
android的system.img分为两种,
一种是raw ext4 image,其特点是完整的ext4分区镜像(包含很多全零的无效填充区),可以直接使用mount进行挂载,因此比较大
$ file system.img
system_raw.img: Linux rev 1.0 ext4 filesystem data, UUID=xxxx(extents) (large files)
另一种是sparse ext4 image,是一个非常普通的dat文件。由于它将raw ext4进行稀疏描述,因此尺寸比较小(没有全零的无效填充区)
simg2img的位置在“out/host/linux-x86/bin/simg2img”
simg2img源码的位置在“system/core/libsparse”
//sparse image转化成为ext4的raw imge
Usage: simg2img <sparse_image_files> <raw_image_file>
//ext4的raw image to sparse image
Usage: img2simg <raw_image_file> <sparse_image_file>
sparse image
To make the images smaller, and to reduce transfer time, Android generates system.img, userdata.img and cache.img in sparse format. The image is split into chunks of multiples of 4096 bytes. Any chunks that contain no useful data are marked as “Don’t care” and no data is sent.
The format is defined in system/core/libsparse/sparse_format.h and looks like this:
$ system/core/libsparse/simg_dump.py -v out/target/product/manta/cache.img
out/target/product/manta/cache.img: Total of 135168 4096-byte output blocks in 24 input chunks.
input_bytes output_blocks
chunk offset number offset number
1 40 4096 0 1 Raw data
2 4148 4096 1 1 Raw data
3 8256 159744 2 39 Raw data
4 168012 8192 41 2 Raw data
5 176216 1732608 43 423 Raw data
6 1908836 8650752 466 2112 Raw data
7 10559600 4096 2578 1 Raw data
8 10563708 4096 2579 1 Raw data
9 10567816 4096 2580 1 Raw data
10 10571924 0 2581 30187 Don't care
11 10571936 4096 32768 1 Raw data
12 10576044 4096 32769 1 Raw data
13 10580152 0 32770 39 Don't care
14 10580164 8192 32809 2 Raw data
15 10588368 0 32811 32725 Don't care
16 10588380 8192 65536 2 Raw data
17 10596584 0 65538 32766 Don't care
18 10596596 4096 98304 1 Raw data
19 10600704 4096 98305 1 Raw data
20 10604812 0 98306 39 Don't care
21 10604824 8192 98345 2 Raw data
22 10613028 0 98347 32725 Don't care
23 10613040 8192 131072 2 Raw data
24 10621244 0 131074 4094 Don't care
10621244 135168 End
The sparse cache.img is 10621244 bytes (about 10 MiB), but the expanded image is 135168 blocks of 4096, which equals 553648128 bytes (528 MiB), so the sparse file is 1.9% of the size of the full image. Quite a useful saving.
You can tell the AOSP build not to create sparse images by adding this line to your BoardConfig.mk:
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
$ du -sh system* --apparent-size
800M system_raw.img
454M system_sparse.img
参考:http://2net.co.uk/tutorial/android-sparse-image-format