Android OTA升級(一)之Makefile檔案分析

戈壁老王發表於2022-05-27
轉載

概要:

此篇文章主要介紹 Android ota 包(Android L)的編譯製作過程,側重於 Makefile 中編譯 ota 的流程,從指定 target 到編譯 cmd 等流程。

主要流程:

原始碼分析:

build/core/Makefile:

.PHONY: otapackage
otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)

otapackage 偽命令,即執行 make otapackage 時,將編譯$(INTERNAL_OTA_PACKAGE_TARGET)目標

$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS)
    @echo "Package OTA: $@"
ifneq ($(TARGET_USERIMAGES_USE_UBIFS),true)
  ifeq (yes, $(filter $(TRUSTONIC_TEE_SUPPORT) $(MTK_ATF_SUPPORT),yes))
      $(hide) MTK_SECURITY_SW_SUPPORT=$(MTK_SECURITY_SW_SUPPORT) MKBOOTIMG=$(MKBOOTIMG) \
         ./build/tools/releasetools/ota_from_target_files -v \
         --block \
         -p $(HOST_OUT) \
         -k $(KEY_CERT_PAIR) \
         -z $(PRODUCT_OUT)/trustzone.bin \
         $(if $(OEM_OTA_CONFIG), -o $(OEM_OTA_CONFIG)) \
         $(BUILT_TARGET_FILES_PACKAGE) $@
  else
      $(hide) MTK_SECURITY_SW_SUPPORT=$(MTK_SECURITY_SW_SUPPORT) MKBOOTIMG=$(MKBOOTIMG) \
         ./build/tools/releasetools/ota_from_target_files -v \
         --block \
         -p $(HOST_OUT) \
         -k $(KEY_CERT_PAIR) \
         $(if $(OEM_OTA_CONFIG), -o $(OEM_OTA_CONFIG)) \
         $(BUILT_TARGET_FILES_PACKAGE) $@
  endif
else
    $(hide) MTK_SECURITY_SW_SUPPORT=$(MTK_SECURITY_SW_SUPPORT) ./build/tools/releasetools/ota_from_target_files -v \
       -n \
       -g \
       -p $(HOST_OUT) \
       -k $(KEY_CERT_PAIR) \
       $(BUILT_TARGET_FILES_PACKAGE) $@
endif
ifeq ($(strip $(MTK_FW_UPGRADE)), yes)
#    @echo "Package FWUpgradePackage"
#    bash $(FWUPGRADEPACKAGE_SH) $(PRODUCT_OUT) $(KEY_CERT_PAIR)
endif

依賴兩部分:

$(BUILT_TARGET_FILES_PACKAGE)$(DISTTOOLS)

然後先找$(BUILT_TARGET_FILES_PACKAGE)BUILT_TARGET_FILES_PACKAGE:= (intermediates)/(intermediates)/(intermediates)/(name).zip 實際為:full_p92s_hd-target_files-eng.wan.zip

# -----------------------------------------------------------------
# A zip of the directories that map to the target filesystem.
# This zip can be used to create an OTA package or filesystem image
# as a post-build step.
#
name := $(TARGET_PRODUCT)
ifeq ($(TARGET_BUILD_TYPE),debug)
  name := $(name)_debug
endif
name := $(name)-target_files-$(FILE_NAME_TAG)

以上這些步驟主要確定 name 變數名稱 name:=(project−name)−targetfiles−(project-name)-target_files-(project−name)−targetfiles−(FILE_NAME_TAG) ,假設 project-name=p92 FILE_NAME_TAG=eng , 則:

name := p92-target_files-eng
intermediates := $(call intermediates-dir-for,PACKAGING,target_files)

此處呼叫了一個函式:intermediates-dir-for,我們來解讀一下它的定義,就知道這句話的意思了。它定義在build/core/definitions.mk 中,如下:

 $(1): target class, like "APPS"
 $(2): target name, like "NotePad"
 $(3): if non-empty, this is a HOST target.
 $(4): if non-empty, force the intermediates to be COMMON
 $(5): if non-empty, force the intermedistes to be for the 2ndarch
define intermediates-dir-for
$(strip \
    $(eval _idfClass :=$(strip $(1))) \
    $(if $(_idfClass),, \
        $(error$(LOCAL_PATH): Class not defined in call to intermediates-dir-for)) \
    $(eval _idfName :=$(strip $(2))) \
    $(if $(_idfName),, \
        $(error$(LOCAL_PATH): Name not defined in call to intermediates-dir-for)) \
    $(eval _idfPrefix :=$(if $(strip $(3)),HOST,TARGET)) \
    $(eval_idf2ndArchPrefix := $(if $(strip $(5)),$(TARGET_2ND_ARCH_VAR_PREFIX))) \
    $(if $(filter$(_idfPrefix)-$(_idfClass),$(COMMON_MODULE_CLASSES))$(4), \
        $(eval _idfIntBase:= $($(_idfPrefix)_OUT_COMMON_INTERMEDIATES)) \
      ,$(if $(filter$(_idfClass),SHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP),\
          $(eval_idfIntBase := $($(_idf2ndArchPrefix)$(_idfPrefix)_OUT_INTERMEDIATES)) \
       ,$(eval _idfIntBase:= $($(_idfPrefix)_OUT_INTERMEDIATES)) \
       ) \
     ) \
   $(_idfIntBase)/$(_idfClass)/$(_idfName)_intermediates \
)
endif

傳入的引數:$1= PACKAGING , $2=target-files, $3及以後的引數為空。

所以執行下來:

  - _idfClass := PACKAGING
  - _idfName := target_files
  - _idfPrefix := TARGET  (以為$3為空,所以if函式走到else part 為TARGET)
  - _idfIntBase := TARGET_OUT_INTERMEDIATES 

由於這個巨集在 build/core/envsetup.mk 中有定義:

TARGET_OUT_INTERMEDIATES := (PRODUCTOUT)/obj(out/target/product/(PRODUCT_OUT)/obj (out/target/product/(PRODUCTOUT)/obj(out/target/product/(project)/obj)

執行結果:

out/target/product/$(project)/obj/PACKAGING/target_files_intermediates

所以這個函式呼叫之後:intermediates := out/target/product/$(project)/obj/PACKAGING/target-files_intermeidates

BUILT_TARGET_FILES_PACKAGE := $(intermediates)/$(name).zip
$(BUILT_TARGET_FILES_PACKAGE): intermediates := $(intermediates)
$(BUILT_TARGET_FILES_PACKAGE): \
        zip_root := $(intermediates)/$(name)

以上幾句同樣是對目標等變數賦值:

BUILT_TARGET_FILES_PACKAGE := out/target/product/$(project)/obj/PACKAGING/target-files_intermeidates/p92-target_files-eng.zip (這個即是將要生成的目標檔案)

然後設定兩個目標指定變數:intermediateszip_root,即這兩個變數只在 BUILT_TARGET_FILES_PACKAGE 這個目標上下文有效(類似於C語言的區域性變數)
Intermediates:= out/target/product/$(project)/obj/PACKAGING/target-files_intermeidates
zip_root := out/target/product/$(project)/obj/PACKAGING/target-files_intermeidates/p92-target_files-eng

# $(1): Directory to copy
# $(2): Location to copy it to
# The "ls -A" is to prevent "acp s/* d" from failing if s is empty.
define package_files-copy-root
  if [ -d "$(strip $(1))" -a "$$(ls -A $(1))" ]; then \
    mkdir -p $(2) && \
    $(ACP) -rd $(strip $(1))/* $(2); \
  fi
endef

以上定義了一個 copy 檔案的函式,有兩個引數 $1,$2,把 $1 中的內容拷到 $2 中。

built_ota_tools := \
    $(call intermediates-dir-for,EXECUTABLES,applypatch)/applypatch \
    $(call intermediates-dir-for,EXECUTABLES,applypatch_static)/applypatch_static \
    $(call intermediates-dir-for,EXECUTABLES,check_prereq)/check_prereq \
    $(call intermediates-dir-for,EXECUTABLES,sqlite3)/sqlite3
ifeq ($(TARGET_ARCH),arm64)
  built_ota_tools += $(call intermediates-dir-for,EXECUTABLES,updater,,,t)/updater
else
  built_ota_tools += $(call intermediates-dir-for,EXECUTABLES,updater)/updater
endif

以上主要做兩件事情:

  1. applypatch … sqlite3 等可執行檔案(obj/EXECUTABLES/…目錄下)賦值給 built_ota_tools
  2. updater 可執行檔案追加賦值給 built_ota_tools。這裡值得注意的是 updater 的呼叫引數:(EXECUTABLES,updater,,,t),存在 $5 ,結合上文對 intermediates-dir-for 函式分析可得到:

    $(eval_idfIntBase := ((((_idf2ndArchPrefix)$(_idfPrefix)_OUT_INTERMEDIATES))
      可得到:idfIntBase :=$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES:= $(PRODUCT_OUT)/obj_$(TARGET_2ND_ARCH) :=out/target/product/$(project)/obj_arm

所以最後返回:out/target/product/$(project)/obj_arm/updater_intermediates/(updater)

可發現呼叫intermediates-dir-for此函式,如果存在引數 $5,並且 _idfClassSHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP 中,則 idfIntBase := out/target/product/$(project)/obj_arm (而非obj)。最終 built_ota_tools := applypatchapplypatch_static check_prereq sqlite3 updater 這幾支檔案(目錄忽略)

$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)

$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_API_VERSION := $(RECOVERY_API_VERSION)
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_FSTAB_VERSION := $(RECOVERY_FSTAB_VERSION)

ifeq ($(TARGET_RELEASETOOLS_EXTENSIONS),)
# default to common dir for device vendor
$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_DEVICE_DIR)/../common
else
$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_RELEASETOOLS_EXTENSIONS)
endif
  1. built_ota_tools 賦值給目標制定變數 PRIVATE_OTA_TOOLS
  2. 分別對 PRIVATE_RECOVERY_API_VERSION, PRIVATE_RECOVERY_FSTAB_VERSION 賦值,其中 RECOVERY_API_VERSION , RECOVERY_FSTAB_VERSION 這兩個變數在 bootable/recovery/Android.mk 中有定義:

    RECOVERY_API_VERSION:= 3
    RECOVERY_FSTAB_VERSION:= 2
  3. tool_extensions 賦值
# Depending on the various images guarantees that the underlying
# directories are up-to-date.
$(BUILT_TARGET_FILES_PACKAGE): \
        $(INSTALLED_BOOTIMAGE_TARGET) \
        $(INSTALLED_RADIOIMAGE_TARGET) \
        $(INSTALLED_RECOVERYIMAGE_TARGET) \
        $(INSTALLED_SYSTEMIMAGE) \
        $(INSTALLED_USERDATAIMAGE_TARGET) \
        $(INSTALLED_CACHEIMAGE_TARGET) \
        $(INSTALLED_VENDORIMAGE_TARGET) \
        $(INSTALLED_ANDROID_INFO_TXT_TARGET) \
        $(SELINUX_FC) \
        $(built_ota_tools) \
        $(APKCERTS_FILE) \
        $(HOST_OUT_EXECUTABLES)/fs_config \
        | $(ACP)

為目標添(out/…/obj/PACKAGING/ target-files_intermeidates/p92-target_files-eng.zip)加依賴,分為兩種依賴,“|”前為普通依賴,即這些依賴 INSTALLED_BOOTIMAGE_TARGET 發生改變,maketarget時目標也要重新構建;“|”後為 order-only 依賴,表示 ACP 這個變數若發生改變,而 target 已經存在時則不需要被重建,若第一次生成則需要重建。

ifeq ($(TARGET_USERIMAGES_USE_EXT4),true)
$(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_CACHEIMAGE_TARGET)
Endif

繼續新增依賴 $(INSTALLED_CACHEIMAGE_TARGET)

@echo "Package target files: $@"
    $(hide) rm -rf $@ $(zip_root)
    $(hide) mkdir -p $(dir $@) $(zip_root)
    @# Components of the recovery image
    $(hide) mkdir -p $(zip_root)/RECOVERY
    $(hide) $(call package_files-copy-root, \
        $(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/RECOVERY/RAMDISK)
ifdef INSTALLED_KERNEL_TARGET
    $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET) $(zip_root)/RECOVERY/kernel
    $(hide) $(ACP) $(recovery_ramdisk) $(zip_root)/RECOVERY/ramdisk
ifeq ($(MTK_HEADER_SUPPORT),yes)
    $(hide) $(ACP) $(recovery_ramdisk_bthdr) $(zip_root)/RECOVERY/ramdisk-bthdr
endif
endif
ifdef INSTALLED_2NDBOOTLOADER_TARGET
    $(hide) $(ACP) \
        $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/RECOVERY/second
endif
ifdef BOARD_KERNEL_CMDLINE
    $(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/RECOVERY/cmdline
endif
ifdef BOARD_KERNEL_BASE
    $(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/RECOVERY/base
endif
ifdef BOARD_KERNEL_PAGESIZE
    $(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/RECOVERY/pagesize
endif
ifdef BOARD_RAMDISK_OFFSET
    $(hide) echo "$(BOARD_RAMDISK_OFFSET)" > $(zip_root)/RECOVERY/ramdisk_offset
endif
ifdef BOARD_KERNEL_OFFSET
    $(hide) echo "$(BOARD_KERNEL_OFFSET)" > $(zip_root)/RECOVERY/kernel_offset
endif
ifdef BOARD_TAGS_OFFSET
    $(hide) echo "$(BOARD_TAGS_OFFSET)" > $(zip_root)/RECOVERY/tags_offset
endif
    $(hide) if [ -f $(PRODUCT_OUT)/custom_build_verno ]; then \
              cat $(PRODUCT_OUT)/custom_build_verno > $(zip_root)/RECOVERY/board; \
            fi

    @# Components of the boot image
    $(hide) mkdir -p $(zip_root)/BOOT
    $(hide) $(call package_files-copy-root, \
        $(TARGET_ROOT_OUT),$(zip_root)/BOOT/RAMDISK)
ifdef INSTALLED_KERNEL_TARGET
    $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/kernel
    $(hide) $(ACP) $(INSTALLED_RAMDISK_TARGET) $(zip_root)/BOOT/ramdisk
endif
ifdef INSTALLED_2NDBOOTLOADER_TARGET
    $(hide) $(ACP) \
        $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
endif
ifdef BOARD_KERNEL_CMDLINE
    $(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
endif
ifdef BOARD_KERNEL_BASE
    $(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base
endif
ifdef BOARD_RAMDISK_OFFSET
    $(hide) echo "$(BOARD_RAMDISK_OFFSET)" > $(zip_root)/BOOT/ramdisk_offset
endif
ifdef BOARD_KERNEL_OFFSET
    $(hide) echo "$(BOARD_KERNEL_OFFSET)" > $(zip_root)/BOOT/kernel_offset
endif
ifdef BOARD_TAGS_OFFSET
    $(hide) echo "$(BOARD_TAGS_OFFSET)" > $(zip_root)/BOOT/tags_offset
endif
ifdef BOARD_KERNEL_PAGESIZE
    $(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/BOOT/pagesize
endif

    $(hide) if [ -f $(PRODUCT_OUT)/custom_build_verno ]; then \
              cat $(PRODUCT_OUT)/custom_build_verno > $(zip_root)/BOOT/board; \
            fi

    $(hide) $(foreach t,$(INSTALLED_RADIOIMAGE_TARGET),\
                mkdir -p $(zip_root)/RADIO; \
                $(ACP) $(t) $(zip_root)/RADIO/$(notdir $(t));)
    @# Contents of the system image
    $(hide) $(call package_files-copy-root, \
        $(SYSTEMIMAGE_SOURCE_DIR),$(zip_root)/SYSTEM)
    @# Contents of the data image
    $(hide) $(call package_files-copy-root, \
        $(TARGET_OUT_DATA),$(zip_root)/DATA)
    @# Contents of the apd image
    $(hide) $(call package_files-copy-root, \
        $(TARGET_OUT_APD),$(zip_root)/APD)
ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
    @# Contents of the vendor image
    $(hide) $(call package_files-copy-root, \
        $(TARGET_OUT_VENDOR),$(zip_root)/VENDOR)
endif
#wschen 2012-11-07
    $(if $(BOARD_CUSTOMIMAGE_PARTITION_SIZE), \
    $(hide) $(call package_files-copy-root, \
        $(TARGET_CUSTOM_OUT),$(zip_root)/CUSTOM))
    @# Extra contents of the OTA package
    $(hide) mkdir -p $(zip_root)/OTA/bin
    $(hide) $(ACP) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/
    $(hide) $(ACP) $(PRIVATE_OTA_TOOLS) $(zip_root)/OTA/bin/

上面內容主要是在 zip_root 目錄下建立相應升級分割槽需要的目錄,並把 out 目錄下對應的檔案 copy 到相應目錄下。如果需要新增一個新分割槽到 ota 中,則需要在上面做一些修改,可參考 apd 分割槽。

@# Security information of the OTA package
    @echo "[SEC OTA] Adding Security information to OTA package"
    @echo "[SEC OTA] path : vendor/mediatek/proprietary/custom/$(MTK_BASE_PROJECT)/security/recovery/SEC_VER.txt"
    $(hide) $(ACP) vendor/mediatek/proprietary/custom/$(MTK_BASE_PROJECT)/security/recovery/SEC_VER.txt $(zip_root)/OTA/
    -$(hide) $(ACP) $(PRODUCT_OUT)/trustzone.bin $(zip_root)/OTA/
    @# Files that do not end up in any images, but are necessary to
    @# build them.
    $(hide) mkdir -p $(zip_root)/META
    $(hide) $(ACP) $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt
    $(hide) if test -e $(tool_extensions)/releasetools.py; then $(ACP) $(tool_extensions)/releasetools.py $(zip_root)/META/; fi
    $(hide)    echo "$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt
    $(hide) echo "recovery_api_version=$(PRIVATE_RECOVERY_API_VERSION)" > $(zip_root)/META/misc_info.txt
    $(hide) echo "fstab_version=$(PRIVATE_RECOVERY_FSTAB_VERSION)" >> $(zip_root)/META/misc_info.txt
fdef BOARD_FLASH_BLOCK_SIZE
    $(hide) echo "blocksize=$(BOARD_FLASH_BLOCK_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
    $(hide) echo "boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
    $(hide) echo "recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
ifdef TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS
    @# TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS can be empty to indicate that nothing but defaults should be used.
    $(hide) echo "recovery_mount_options=$(TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)" >> $(zip_root)/META/misc_info.txt
else
    $(hide) echo "recovery_mount_options=$(DEFAULT_TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)" >> $(zip_root)/META/misc_info.txt
endif
    $(hide) echo "tool_extensions=$(tool_extensions)" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "default_system_dev_certificate=$(DEFAULT_KEY_CERT_PAIR)" >> $(zip_root)/META/misc_info.txt
ifdef PRODUCT_EXTRA_RECOVERY_KEYS
    $(hide) echo "extra_recovery_keys=$(PRODUCT_EXTRA_RECOVERY_KEYS)" >> $(zip_root)/META/misc_info.txt
endif
    $(hide) echo 'mkbootimg_args=$(BOARD_MKBOOTIMG_ARGS)' >> $(zip_root)/META/misc_info.txt
    $(hide) echo "use_set_metadata=1" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "multistage_support=1" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "update_rename_support=1" >> $(zip_root)/META/misc_info.txt
    $(hide) echo "blockimgdiff_versions=1,2" >> $(zip_root)/META/misc_info.txt
ifeq ($(MTK_HEADER_SUPPORT),yes)
    $(hide) echo "mtk_header_support=1" >> $(zip_root)/META/misc_info.txt
endif
ifneq ($(OEM_THUMBPRINT_PROPERTIES),)
    # OTA scripts are only interested in fingerprint related properties
    $(hide) echo "oem_fingerprint_properties=$(OEM_THUMBPRINT_PROPERTIES)" >> $(zip_root)/META/misc_info.txt
endif
ifeq ($(TARGET_USERIMAGES_USE_UBIFS),true)
    $(call generate-ubifs-prop-dictionary, $(zip_root)/META/misc_info.txt)
endif
    $(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
ifeq ($(TRUSTONIC_TEE_SUPPORT),yes)
    $(hide) ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root) $(PRODUCT_OUT)
else
    $(hide) ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root) $(TRUSTONIC_TEE_SUPPORT)
endif
ifeq ($(strip $(MTK_SECURITY_SW_SUPPORT)), yes)
    #security boot signature
    $(hide) $(SHELL) $(SECURITY_SIG_TOOL)
    $(hide) cp $(PRODUCT_OUT)/sig/boot.sig $(zip_root)/META/
    $(hide) cp $(PRODUCT_OUT)/sig/recovery.sig $(zip_root)/META/
    $(hide) cp $(PRODUCT_OUT)/sig/recovery.sig $(zip_root)/SYSTEM/etc/
Endif

繼續做一些 copy 檔案的動作。

@# Zip everything up, preserving symlinks
    $(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .)
    @# Run fs_config on all the system, vendor, boot ramdisk,
    @# and recovery ramdisk files in the zip, and save the output

把 zip_root 中的內容壓縮成目標壓縮包 zip –qry …/p92-target_files-eng.zip

$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="VENDOR/" } /^VENDOR\// {print "vendor/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/vendor_filesystem_config.txt
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="APD/" } /^APD\// {print "apd/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/apd_filesystem_config.txt
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/boot_filesystem_config.txt
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt
#wschen 2012-11-07
    $(if $(BOARD_CUSTOMIMAGE_PARTITION_SIZE), \
    $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="CUSTOM/" } /^CUSTOM\// {print "custom/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/custom_filesystem_config.txt)

為需要ota升級的分割槽目錄及其目錄下的檔案新增selinux許可權,並把這些許可權內容輸出到X_filesystem_config.txt 檔案中,如meta/apd_filesystem_config.txt:

apd 0 0 755selabel=u:object_r:apd_file:s0 capabilities=0x0
apd/test.ini 0 2000 777selabel=u:object_r:apd_file:s0 capabilities=0x0
apd/apd.txt 0 2000 777selabel=u:object_r:apd_file:s0 capabilities=0x0
apd/apd.ini 0 2000 777selabel=u:object_r:apd_file:s0 capabilities=0x0
$(hide) (cd $(zip_root) && zip -q ../$(notdir $@) META/*filesystem_config.txt)

把這些 *filesystem_config.txt 檔案一併放置目標壓縮包中

$(hide) ./build/tools/releasetools/add_img_to_target_files -p $(HOST_OUT) $@

這個檔案 add_img_to_target_files.py 很重要,主要功能是生成一個 images 資料夾,存放著生成的各種 img(包括需要新增至 ota 升級的分割槽),如下圖。如果需要把一個新分割槽新增至 ota 升級包中,這個檔案則需要修改,可參考 custom/vendor 分割槽的新增方法。

$(hide) ./build/tools/releasetools/replace_img_from_target_files.py $@ $(PRODUCT_OUT)

要了解這句話的主要目的,來看一下 replace_img_from_target_files.py 檔案的註解:

'''
Given a target-files zipfilethat does contain images (ie, does

have an IMAGES/ top-level subdirectory), replace the images to

the output dir.

Usage: replace_img_from_target_files target_files output
'''

把目標壓縮包 out/target/product/(project)/obj/PACKAGING/target−filesintermeidates/p92−targetfiles−eng.zip 中的images/ 路徑下的各個 img 輸出到 out/target/product/(project)/obj/PACKAGING/target-files_intermeidates/p92-target_files-eng.zip中的 images/ 路徑下的各個 img 輸出到 out/target/product/(project)/obj/PACKAGING/target−filesintermeidates/p92−targetfiles−eng.zip 中的 images/ 路徑下的各個 img 輸出到 out/target/product/(project-name)/ 目錄下。比如替換 out… 目錄下原來的 boot.img,system.img,apd.img 等。

然後來看一下另外一個依賴:

DISTTOOLS :=  $(HOST_OUT_EXECUTABLES)/minigzip \
      $(HOST_OUT_EXECUTABLES)/mkbootfs \
      $(HOST_OUT_EXECUTABLES)/mkbootimg \
      $(HOST_OUT_EXECUTABLES)/fs_config \
      $(HOST_OUT_EXECUTABLES)/mkyaffs2image \
      $(HOST_OUT_EXECUTABLES)/zipalign \
      $(HOST_OUT_EXECUTABLES)/bsdiff \
      $(HOST_OUT_EXECUTABLES)/imgdiff \
      $(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar \
      $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
      $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \
      $(HOST_OUT_EXECUTABLES)/make_ext4fs \
      $(HOST_OUT_EXECUTABLES)/simg2img \
      $(HOST_OUT_EXECUTABLES)/e2fsck \
      $(HOST_OUT_EXECUTABLES)/build_verity_tree \
      $(HOST_OUT_EXECUTABLES)/verity_signer \
      $(HOST_OUT_EXECUTABLES)/append2simg

其實就是定義 disttoolsout/host/ 目錄下的一些可執行檔案。

最後再跳到終極目標的 cmd 開始執行:

$(hide) MTK_SECURITY_SW_SUPPORT=$(MTK_SECURITY_SW_SUPPORT) MKBOOTIMG=$(MKBOOTIMG) \
    ./build/tools/releasetools/ota_from_target_files -v \
         --block \
         -p $(HOST_OUT) \
         -k $(KEY_CERT_PAIR) \
         $(if $(OEM_OTA_CONFIG), -o $(OEM_OTA_CONFIG)) \
         $(BUILT_TARGET_FILES_PACKAGE) $@

所以跳到 ota_from_target_files python 檔案中,接下來就要看 ota_from_target_files 這個檔案的作用了。

相關文章