最近尝试着修改Android P的编译脚本,目的是为了将系统源码和BSP源码分开编译。
由于厂家定制,Android内核的源码一般都在vendor目录下,本文尝试去掉vendor中的kernel源码,还能正常编译Android其他源码,便于做系统开发或者app发开,不依赖kernel源码编译。
相关源码:
build/make/core/Makefile
device/fsl/imx8q/mek_8q/AndroidBoard.mk
device/fsl/imx8q/mek_8q/BoardConfig.mk
device/fsl/common/build/dtbo.mk
system/core/fs_mgr/fs_mgr_avb.cpp
vendor\nxp-opensource\uboot-imx\lib\avb\libavb\avb_slot_verify.c
vendor\nxp-opensource\uboot-imx\lib\avb\libavb\avb_vbmeta_image.h
升级镜像文件包括:
boot.img
bootloader-imx8qm.img
bootloader-imx8qm-xen.img
dtbo-imx8qm.img
dtbo-imx8qm-xen.img
vendor.img
partition-table-28GB.img
system.img
spl-imx8qm.bin
libusb-1.0.dll
spl-imx8qm-xen.bin
u-boot-imx8qm-xen-dom0.imx
uuu.exe
uuu_imx_android_flash.bat
vbmeta-imx8qm.img
vbmeta-imx8qm-xen.img
AndroidBoard.mk中去掉kernel和uboot的编译脚本mk文件:
LOCAL_PATH := $(call my-dir)
# build without kernel and uboot,rm by sunxiaolin 20191021
#include device/fsl/common/build/kernel.mk
#include device/fsl/common/build/uboot.mk
include device/fsl/common/build/dtbo.mk
include device/fsl/common/build/imx-recovery.mk
include device/fsl/common/build/gpt.mk
include $(LOCAL_PATH)/AndroidUboot.mk
include $(FSL_PROPRIETARY_PATH)/fsl-proprietary/media-profile/media-profile.mk
ifneq ($(PRODUCT_IMX_CAR),true)
include $(FSL_PROPRIETARY_PATH)/fsl-proprietary/sensor/fsl-sensor.mk
endif
继续去掉dtbo的编译,因为dtbo.mk中包含了vbmeta-imx8qm.img的编译,而且vbmeta需要跟系统镜像system.img放在一起编译。dtbo-imx8qm.img则需要跟kernel,uboot部分一起编译。
1、去掉kernel_imx相关的编译内容
2、去掉dtboimage: $(BOARD_PREBUILT_DTBOIMAGE)相关的编译内容
3、修改vbmeta的编译内容,主要去掉
echo $(PRODUCT_OUT)/dtbo-$${DTS_PLATFORM}.img
; \echo $(PRODUCT_OUT)/recovery-$${DTS_PLATFORM}.img
; \1、去掉所有vendor/目录的拷贝操作,例如:PRODUCT_COPY_FILES +=
device/fsl/imx8q/etc/wifi/fw_bcmdhd.bin:vendor/etc/wifi/fw_bcmdhd.bin
2、去掉所有KERNEL_OUT目录的拷贝操作,例如:
ifeq ($(PRODUCT_IMX_CAR_M4),true)
BOARD_VENDOR_KERNEL_MODULES += \
$(KERNEL_OUT)/drivers/hid/usbhid/usbhid.ko \
BOARD_RECOVERY_KERNEL_MODULES += \
$(KERNEL_OUT)/drivers/gpu/drm/bridge/ds90ub947.ko \
endif
build/make/core/Makefile文件是整个Android编译的核心文件。
1、去掉boot.img部分的编译内容,例如:
#INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
2、去掉vendor.img部分的编译内容。例如:
#BUILT_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vendor.img
3、去掉dtbo.img部分的编译内容。例如:
#INSTALLED_DTBOIMAGE_TARGET := $(PRODUCT_OUT)/dtbo.img
4、去掉avb校验,注释一下部分的代码:
#ifdef BOARD_AVB_BOOT_KEY_PATH
#$(eval $(call check-and-set-avb-chain-args,BOOT))
#else
#INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
# --include_descriptors_from_image $(INSTALLED_BOOTIMAGE_TARGET)
#endif
修改了以上这么多之后,系统可以分开编译过。
分开之后,Android系统打包升级Image包括:
partition-table-28GB.img
system.img
spl-imx8qm.bin
libusb-1.0.dll
spl-imx8qm-xen.bin
u-boot-imx8qm-xen-dom0.imx
uuu.exe
uuu_imx_android_flash.bat
vbmeta-imx8qm.img
vbmeta-imx8qm-xen.img
Android系统内核打包升级Image包括:
boot.img
bootloader-imx8qm.img
bootloader-imx8qm-xen.img
dtbo-imx8qm.img
dtbo-imx8qm-xen.img
vendor.img
使用uuu.exe工具进行正常升级,发现系统起不来,报错:
Read public key error
AVB TIPC client not initialized
vendor.img avb校验失败:
avb主要是bootloader的校验和vendor的校验,校验失败后系统启动不了。
vendor\nxp-opensource\uboot-imx\lib\avb\libavb\avb_slot_verify.c
vendor\nxp-opensource\uboot-imx\lib\avb\libavb\avb_vbmeta_image.h
avb_vbmeta_image.h中定义了
/* Flags for the vbmeta image.
*
* AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED: If this flag is set,
* hashtree image verification will be disabled.
*
* AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set,
* verification will be disabled and descriptors will not be parsed.
*/
typedef enum {
AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = (1 << 0),
AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED = (1 << 1)
} AvbVBMetaImageFlags;
位运算:
(1 << 0),即0x00000001
(1 << 1),即0x00000010
这两个flag分别表示是否使能dm-verity和verification功能,默认是会开启这两个验证功能。
vendor\nxp-opensource\uboot-imx\lib\avb\libavb\avb_slot_verify.c
static AvbSlotVerifyResult load_and_verify_vbmeta(){
//省略一部分代码
//...
/* If verification has been disabled by setting a bit in the image,
* we're done... except that we need to load the entirety of the
* requested partitions.
*/
//修改vbmeta_header.flags标志为AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
vbmeta_header.flags = AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
AvbSlotVerifyResult sub_ret;
avb_debugv(
full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
/* If load_requested_partitions() fail it is always a fatal
* failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
* than recoverable (e.g. one where result_should_continue()
* returns true) and we want to convey that error.
*/
sub_ret = load_requested_partitions(
ops, requested_partitions, ab_suffix, slot_data);
if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
ret = sub_ret;
}
goto out;
}
//省略一部分代码
//...
/* Compare the flags for top-level VBMeta struct with flags in
* the command-line descriptor so command-line snippets only
* intended for a certain mode (dm-verity enabled/disabled)
* are skipped if applicable.
*/
apply_cmdline = true;
//修改toplevel_vbmeta_flags标志为AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED
toplevel_vbmeta_flags = AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED;
if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
if (kernel_cmdline_desc.flags &
AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
apply_cmdline = false;
}
} else {
if (kernel_cmdline_desc.flags &
AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
apply_cmdline = false;
}
}
}
AvbSlotVerifyResult avb_slot_verify(){
//省略一部分代码
//...
/* If verification is disabled, we are done ... we specifically
* don't want to add any androidboot.* options since verification
* is disabled.
*/
//add by sunxiaolin 20191107
//修改toplevel_vbmeta.flags标志为AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
toplevel_vbmeta.flags = (1 << 1);
if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
/* Since verification is disabled we didn't process any
* descriptors and thus there's no cmdline... so set root= such
* that the system partition is mounted.
*/
avb_assert(slot_data->cmdline == NULL);
slot_data->cmdline =
avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
if (slot_data->cmdline == NULL) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto fail;
}
} else {
/* Add options - any failure in avb_append_options() is either an
* I/O or OOM error.
*/
AvbSlotVerifyResult sub_ret = avb_append_options(ops,
slot_data,
&toplevel_vbmeta,
algorithm_type,
hashtree_error_mode);
if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
ret = sub_ret;
goto fail;
}
}
//省略一部分代码
//...
}
禁止dm-verity还有一种方法,即在升级成功后,使用:
adb disable-verity
重启生效。
还需要修改vendor校验
system/core/fs_mgr/fs_mgr_avb.cpp
FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) {
//省略一部分代码
//...
// Checks whether FLAGS_VERIFICATION_DISABLED is set:
// - Only the top-level vbmeta struct is read.
// - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s)
// and AVB HASHTREE descriptor(s).
AvbVBMetaImageHeader vbmeta_header;
avb_vbmeta_image_header_to_host_byte_order(
(AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
&vbmeta_header);
//将vbmeta_header.flags设置为:AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
vbmeta_header.flags = AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
bool verification_disabled =
((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
if (verification_disabled) {
avb_handle->status_ = kAvbHandleVerificationDisabled;
} else {
// Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline.
std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
if (!avb_verifier) {
LERROR << "Failed to create FsManagerAvbVerifier";
return nullptr;
}
if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
LERROR << "VerifyVbmetaImages failed";
return nullptr;
}
// Checks whether FLAGS_HASHTREE_DISABLED is set.
bool hashtree_disabled =
((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
if (hashtree_disabled) {
avb_handle->status_ = kAvbHandleHashtreeDisabled;
}
}
//省略一部分代码
//...
}