Android add_img_to_target_files.py分析

add_img_to_target_files.py
文件位置: build/tools/releasetools/add_img_to_target_files.py
Android 在編譯成生成OTA文件時會被調用.
(注)這裏只關心system.img創建流程,其他img也是類似的.
原生Android 命令幫助

$ build/tools/releasetools/add_img_to_target_files.py -h

Given a target-files zipfile that does not contain images (ie, does
not have an IMAGES/ top-level subdirectory), produce the images and
add them to the zipfile.

Usage:  add_img_to_target_files [flag] target_files

  -a  (--add_missing)
      Build and add missing images to "IMAGES/". If this option is
      not specified, this script will simply exit when "IMAGES/"
      directory exists in the target file.

  -r  (--rebuild_recovery)
      Rebuild the recovery patch and write it to the system image. Only
      meaningful when system image needs to be rebuilt.

  --replace_verity_private_key
      Replace the private key used for verity signing. (same as the option
      in sign_target_files_apks)

  --replace_verity_public_key
       Replace the certificate (public key) used for verity verification. (same
       as the option in sign_target_files_apks)

  --is_signing
      Skip building & adding the images for "userdata" and "cache" if we
      are signing the target files.

  -p  (--path)  <dir>
      Prepend <dir>/bin to the list of places to search for binaries
      run by this script, and expect to find jars in <dir>/framework.

  -s  (--device_specific) <file>
      Path to the python module containing device-specific
      releasetools code.

  -x  (--extra)  <key=value>
      Add a key/value pair to the 'extras' dict, which device-specific
      extension code may look at.

  -v  (--verbose)
      Show command lines being executed.

  -h  (--help)
      Display this usage message and exit.

示例

$./build/tools/releasetools/add_img_to_target_files.py -a -v -p linux-x86 target_files

一.add_img_to_target_files執行過程

  1. 它會檢查輸入參數
  2. 判斷輸入文件目錄格式(文件夾,ZIP)
  3. 解析META/misc_info.txt 配置參數
  4. 按順序生成boot.img, reovery.img, system.img, vendor.img, vbmate.img, userdata.img
    其中,system.img, vendor.img這兩個比較特殊,是sparse格式的.文件頭以0xED26FF3A開頭,
    boot.img 的文件頭是以 0xEDFE0DD0開頭
    vbmete.img :是 0x30425641開頭的.
    $file IMAGES/boot.img
    IMAGES/boot.img: data
    

這個程序的流程圖:
在這裏插入圖片描述

二.system.img創建過程

  1. 從這AddSystem函數開始調用.
    判斷是否存在system.img,存在,則返回.否則,調用:
    CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system", img,
                  block_list=block_list)
    
  2. 下面是CreateImage代碼, 下面只分析system.img的創建.
def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
  print("creating " + what + ".img...")

  # The name of the directory it is making an image out of matters to
  # mkyaffs2image.  It wants "system" but we have a directory named
  # "SYSTEM", so create a symlink.
  temp_dir = tempfile.mkdtemp()
  OPTIONS.tempfiles.append(temp_dir)
  try:
    os.symlink(os.path.join(input_dir, what.upper()),
               os.path.join(temp_dir, what))
  except OSError as e:
    # bogus error on my mac version?
    #   File "./build/tools/releasetools/img_from_target_files"
    #     os.path.join(OPTIONS.input_tmp, "system"))
    # OSError: [Errno 17] File exists
    if e.errno == errno.EEXIST:
      pass
      
  #info_dict是MATE/misc_info.txt內容,image_props生成Image屬性字典
  #ImagePropFromGlobalDict:Build an image property dictionary from the global dictionary
  image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
  fstab = info_dict["fstab"] 
  mount_point = "/" + what
  if fstab and mount_point in fstab:  
    image_props["fs_type"] = fstab[mount_point].fs_type

  # Use a fixed timestamp (01/01/2009) when packaging the image.
  # Bug: 24377993
  epoch = datetime.datetime.fromtimestamp(0)
  timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
  image_props["timestamp"] = int(timestamp) #保存時間戳

  if what == "system":
    fs_config_prefix = ""
  else:
    fs_config_prefix = what + "_"

  fs_config = os.path.join(
      input_dir, "META/" + fs_config_prefix + "filesystem_config.txt")
  if not os.path.exists(fs_config): #判斷fs_config文件是否存在
    fs_config = None

  # Override values loaded from info_dict.
  if fs_config:
    image_props["fs_config"] = fs_config
  if block_list:
    image_props["block_list"] = block_list.name

  # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
  # build fingerprint).
  uuid_seed = what + "-"
  if "build.prop" in info_dict:
    build_prop = info_dict["build.prop"]
    if "ro.build.fingerprint" in build_prop:
      uuid_seed += build_prop["ro.build.fingerprint"]
    elif "ro.build.thumbprint" in build_prop:
      uuid_seed += build_prop["ro.build.thumbprint"]
  image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
  hash_seed = "hash_seed-" + uuid_seed
  image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
  print(image_props)
'''
 上面的輸出: {'partition_size': '4294967296', 'selinux_fc': 'out/target/product/mt2712 \/obj/PACKAGING/target_files_intermediates/car_mtxxxx_vp1-target_files-eng.xxx/META/file_contexts.bin', 'mount_point': 'system', 'fs_type': 'ext4', 'uuid': '8b37e1c4-2644-587d-98ba-2c4b4051713e', 'avb_enable': 'true', 
 'avb_avbtool': 'avbtool', 'timestamp': 1230739200, 'ramdisk_dir': 'out/target/product/mt2712/obj/PACKAGING/target_files_intermediates/mtxxxx_vp1-target_files-eng.xxx/ROOT', 'block_list': '/home/xxx/xxx_back
 /out/target/product/mt2712/obj/PACKAGING/target_files_intermediates/mtxxxx_vp1-target_files-eng.xxx/IMAGES/system.map', 'fs_config': '/home/xxx/xxx_back/out/target/product/mt2712/obj/PACKAGING
 /target_files_intermediates/mtxxxx_vp1-target_files-eng.xxx/META/filesystem_config.txt', 
 'avb_hashtree_enable': 'true', 'ext_mkuserimg': 'mkuserimg.sh', 'extfs_sparse_flag': '-s', 'squashfs_sparse_flag': '-s', 'avb_salt': 
 '1f142b82683fef0e8b0959e671966be80060f3ccd8cd11287679a64819830199', 'system_root_image': 'true', 'partition_name': 'system', 'ramdisk_fs_config': 'out/target/product/mt2712/obj/PACKAGING/target_files_intermediates/mtxxxx_vp1-target_files-eng.xxx/META/root_filesystem_config.txt', 
 'avb_add_hashtree_footer_args': '--setup_as_rootfs_from_kernel', 'hash_seed': 
 '31c34b75-754c-5bf1-a15f-0f045e3b27f8## 標題'}
'''
  succ = build_image.BuildImage(os.path.join(temp_dir, what),
                                image_props, output_file.name) #生成Image
  #在BuildImage函數中運行下面命令
  '''
  ['mkuserimg.sh', '-s', '/tmp/tmpNrCt3J', '/home/xxx/xxx_back/out/target/product/mt2712/obj/PACKAGING/target_files_intermediates/**/IMAGES/system.img', 'ext4', '/', '4227117056', '-T', '1230739200', 
  '-C', '/tmp/root_fs_configrVsgbS.txt', '-B', '/home/xxx/xxx_back/out/target/product/mt2712/obj/PACKAGING/target_files_intermediates/mtxxxx_vp1-target_files-eng.xxx/IMAGES/system.map', '-L', '/', 
  'out/target/product/mt2712/obj/PACKAGING/target_files_intermediates/mtxxxx_vp1-target_files-eng.xxx/META/file_contexts.bin']
  '''
  assert succ, "build " + what + ".img image failed"

  output_file.Write()
  if block_list:
    block_list.Write()
  #MATE/care_map.txt. 這裏面保存的img是調整前的sparse格式 的數據CHUNK_TYPE_DONT_CARE
  # Set the 'adjusted_partition_size' that excludes the verity blocks of the
  # given image. When avb is enabled, this size is the max image size returned
  # by the avb tool.
  is_verity_partition = "verity_block_device" in image_props
  verity_supported = (image_props.get("verity") == "true" or
                      image_props.get("avb_enable") == "true")
  is_avb_enable = image_props.get("avb_hashtree_enable") == "true"
  print('--------------is_verity_partition-------------------',is_verity_partition)# False
  print('--------------verity_supported-------------------',verity_supported) #True
  print('--------------is_avb_enable-------------------',is_avb_enable) #True
  if verity_supported and (is_verity_partition or is_avb_enable):
    adjusted_blocks_value = image_props.get("partition_size")
    if adjusted_blocks_value:
      adjusted_blocks_key = what + "_adjusted_partition_size"
      info_dict[adjusted_blocks_key] = int(adjusted_blocks_value)/4096 - 1

這裏有個問題需要注意一下
在原生android編譯生成的system.img 和vender.img 都是經過調整後的,所以生成care_map.txt 的內容都都要小一些.
如果已經存在的img. 這是生成的care_map.txt的內容就要大一些.
(注)care_map.txt 是 MATE/care_map.txt

build/tools/releasetools/add_img_to_target_files  -a -v -p linux-x86 target_files

例如:
原生Android生成的.

$ cat care_map.txt 
system
92,0,32766,32768,32770,33025,.....省略
vendor
10,0,17607,32768,32770,32793,.....省略

自己用上面工具生成

system
94,0,32766,32768,32770,33025,.....省略
vendor
14,0,17607,32768,32770,32793,.....省略

爲什麼出現這個問題呢?
因爲add_img_to_target_files生成時,將avbtool 增加footer 計算到了.care_map.txt文件中.
實際care_map.txt文件是保存sprase format 的 Don’t care 數據類型.
care_map.txt
system保存的哪個img
92: 這後面有92個數據 0 輸入數據塊 32766輸出塊偏移量 32768輸出塊
Android 稀疏鏡像格式 (android sparse image format)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章