android system.img打包

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

使用方法:http://blog.csdn.net/asmcvc/article/details/11770851 工具: unyaffs,mkyaffs2image 其中unyaffs有windows版本和linux版本,mkyaffs2image只有linux版本。 windows版本的unyaffs用法: 把system.img复制到unyaffs的相同目录下,cmd命令下cd到unyaffs的目录下,然后执行命令:unyaffs system.img unyaffs会把system.img解压到其目录下。 linux版本的unyaffs用法: 把unyaffs复制到/usr/bin目录下,并修改权限为可执行。 然后cd到system.img目录下(假定目录为system目录),执行命令:unyaffs system.img 然后对system目录下的文件进行修改。 注意:修改完后的文件要修改一下权限,尽量和其他文件的权限保持一致。例如:chmod 644 framework-res.apk mkyaffs2image用法: 复制到/usr/bin目录下,并修改权限为可执行。 这里以打包system目录为system.img为例,执行命令: mkyaffs2image system system.img 然后把新生成的system.img复制替换掉原:adt-bundle-windows-x86\sdk\system-images\android-17\armeabi-v7a\system.img 执行bat批处理命令启动模拟器: D:\adt-bundle-windows-x86\sdk\tools\emulator-arm.exe -avd AndroidVM -partition-size 128 这里以修改android系统启动画面为例: 打开解包目录下的\framework\framework-res.apk 替换图片:framework-res.apk\assets\images\android-logo-mask.png为下图: 然后对\framework\framework-res.apk文件重新签名,复制到linux下后修改文件权限和原来一致。 然后mkyaffs2image system system.img打包生成新的system.img,替换原来的system.img,并启动模拟器,效果图如下: 修改代码: 工具:odextools(参考:《一键odex批量合并工具odextools的重新整理与使用》)、dexopt-wrapper 其中odextools.bat的代码: 批处理有一处bug:每打包一次会把odex文件删除掉,导致在后面的打包过程中会出现找不到:system/framework/core.odex类似的错误,因此只需要在打包完后不删除odex文件即可,找到del /f !apkx!.odex 1>nul 2>nul改为:::del /f !apkx!.odex 1>nul 2>nul,也就是注释掉这一行代码。 具体使用方法(操作在windows下): 在odextools\romdir目录下创建文件夹:system 利用unyaffs解包system.img后,把所有文件复制到system目录下。 然后运行odextools.bat,如图: 选择一个需要整合odex的目录选项即可。odextools.bat会自动设置环境变量,使用baksmali.jar来反编译odex为smali,然后再调用smali.jar打包为classes.dex, 然后再打包到相应的apk包(framework目录下对应的是jar后缀的,实际上也是个apk包),最后再重新签名。 如果要修改代码,则需要把上面重新打包生成的apk文件,利用常规方法反编译后修改smali代码,例如插桩输入log信息。然后再回编译并重新签名。 最后一步:因为system.img中的apk是优化过的,apk主目录下是没有classes.dex文件的,而是一个被优化过的odex文件,用于优化启动速度。 因此需要将修改后的apk包再用dexopt-wrapper优化apk包后生成出odex文件,然后删除apk包里的classes.dex,并在相同目录下放置与apk包同名的odex文件。 按照原system目录的文件结构组织好后,目录复制到linux环境下使用mkyaffs2image重新打包成system.img
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值