Android编译boot.img和bootloader

背景: android 6.0 nxp imx6duallite
一、根目录下 Makefile 如下:
### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###

include 语言跟c语言一样,包含build/core/main.mk

二、接下来简要分析 build/core/main.mk

打开main.mk,G到最后一行,往上分析。可以看到很多编译目标,类似 .PHONY: modules

.PHONY: clean

其中在878行:

.PHONY: droidcore
droidcore:	kernelimage 	\
			kernelmodules	\
			bootloader		\
			files			\
			systemimage		\
			$(INSTALLED_BOOTIMAGE_TARGET)	\
			$(INSTALLED_RECOVERY_TARGET)	\
			$(INSTALLED_USRTDATAIAGE_TARGET) \
			$(INSTALLED_CACHEIMAGE_TARGET)	\
			$(INSTALLED_VERDORIMAGE_TARGET)	\
			$(INSTALLED_FILES_FILE)			\
			ubiimagesgenerate

可以看出,该编译目标为 android的核心编译目标。kernelimage即编译出的目标zImage,systemimage即编译出的system.img, $(INSTALLED_BOOTIMAGE_TARGET)为boot.img。搜索main.mk,查找不到目标的定义。那该定义就是在其他文件中。在main.mk的784行有一句:

include $(BUILD_SYSTEM)/Makefile

BUILD_SYSTEM的值为:

BUILD_SYSTEM := $(TOPDIR)build/core

$(TOPDIR)即为Android源码的根目录。所以从main.mk的784行那一句include 就把build/core/Makefile包含进去了。

  1. 接下来分析目标 kernelimage ⇒ {kernel, dtb}
    打开build/core/Makefile,搜索kernelimage 的定义,如下:
.PHONY: kernelimage
ifneq	($(strip $(TARGET_NO_KERNEL)), true)
KERNEL_CROSS_TOOLCHAIN  := `pwd`/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-
KERNEL_CFLAGS 			:= KCFLAGS=-mno-android
KERNEL_ENV 				:= ARCH=arm CROSS_COMPILE=$(KERNEL_CROSS_TOOLCHAIN) LOADADDR=$(LOAD_KERNEL_ENTRY) $(KERNEL_CFLAGS)
HOST_PROCESSOR 			:= $(shell cat /proc/cpuinfo | grep processor | wc -l)
INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)kernel
TARGET_PREBUILT_KERNEL  := $(PRODUCT_OUT)kernel
KERNEL_CONFIGURE   		:= kernel_imx/.config
TARGET_KERNEL_CONFIGURE := $(PRODUCT_OUT)/.config
KERNEL_ZMAGE 			:= kernel_imx/arch/arm/boot/zImage
KERNEL_OUT				:=$(TARGET_OUT_INTERMEDIATES/KERNEL_OBJ

.PHONY: $(TARGET_PREBUILT_KERNEL)	
kernel.image:	$(TARGET_PREBUILT_KERNEL)

# 默认的内核配置文件
$(KERNEL_CONFIGURE): kernel_imx/arch/arm/configs/$(TARGET_KERNEL_DEFCONF)

# 配置内核
$(TARGET_KERNEL_CONFIGURE): kernel_imx/arch/arm/configs/$(TARGET_KERNEL_DEFCONF) $(KERNEL_CONFIGURE)
		$(MAKE)	-C kernel_imx $(TARGET_KERNEL_DEFCONF) $(KERNEL_ENV)
		install -D $(KERNEL_CONFIGURE) $(TARGET_KERNEL_CONFIGURE)

# 编译uImage 和 dtb,并安装到指定的目录
$(TARGET_PREBUILT_KERNEL): $(TARGET_KERNEL_CONFIGURE)
		$(MAKE) -C kernel_imx -j$(HOST_PROCESSOR) uImage $(KERNEL_ENV)
		$(MAKE) -C kernel_imx	dtbs $(KERNEL_ENV)
		install -D $(KERNEL_ZIMAGE)	 $(PRODUCT_OUT)/kernel
		for dtsplat in $(TARGET_BOARD_DTS_CONFIG); do		   \
				DTS_PLATFORM=`echo $$dtsplat | cut -d':' -f1`; \
				DTS_BOARD=`echo $$dtsplat | cut -d':' -f2`;		\
				install -D kernel_imx/arch/arm/boot/dts/$$DTS_BOARD $(PRODUCT_OUT)/$$DTS_BOARD; \
		done
else
kernelimage:
endif

*整体过程就是配置交叉编译链,默认的配置文件,内核和设备树的输出目录和其他参数。这里用到了make 的 -C 参数,指定编译的源码路径编译。
2.接下来是 kernelmodules

.PHONY:	kernelmodules

kernel_modules_src_list :=
kernel_modules_dist_list :=

$(foreach cf, $(TARGET_KERNEL_MODULES),		\
$(eval _src := $(call word-colon,1,$(cf)))	\
$(eval _dest := $(call word-colon,2,$(cf)))	\
$(eval kernel_modules_src_list	+= $(_src)) \
$(eval kernel_modules_dest_list	+= $(call append-path, $(PRODUCT_OUT), $(_dest))))

ifneq ($(strip $(kernel_modules_src_list)),)
# 编译模块,并拷贝到指定的目录
kernelmodules:	$(TARGET_PREBUILT_KERNEL) | $(ACP)
		$(MAKE) -C kernel_imx modules $(KERNEL_ENV)
		$(hide) $(foreach cf, $(TARGET_KERNEL_MODULES),		\
		$(eval _src := $(call word-colon,1,$(cf)))			\
		$(eval _dest := $(call word-colon,2,$(cf)))			\
		$(eval _full_dest := $(call append-path, $(PRODUCT_OUT), $(_dest))) \
		$(eval _dest_dir  := $(call dir, $(_full_dest)))
		mkdir -p $(_dest_dir)								\
		$(ACP) $(_src) $(_full_dest);						\
		)
		@echo "install kernel modules: $(kernel_modules_src_list)"
else
kernelmodules:
endif

3.目标 $(INSTALLED_BOOTIMAGE_TARGET) ==> boot.img
==> {kernel, dtb, ramdisk}

ifneq ($(strip $(TARGET_NO_KERNEL)), true)
# 编译boot.img的参数
INTERNAL_BOOTIMAGE_ARGS :=	\
		$(addprefix --second , $(INSTALLED_2NDBOOTLOADER_TARGET))	\
		--kernel $(INSTALLED_KERNEL_TARGET)
# ramdisk 参数
ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE), true)
INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
endif

INTERNAL_BOOTIMAGE_FILLES := $(filter-out --%, $(INTERNAL_BOOTIMAGE_ARGS))
# cmdline 参数
BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
ifdef BOARD_KERNEL_CMDLINE
	INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
endif
# base ?
BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
ifdef BOARD_KERNEL_BASE
	INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
endif 
# 页大小的参数
BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
ifdef BOARD_KERNEL_PAGESIZE
	INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
endif
# 生成目标的完整路径文件名
INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img

ifeq ($(TARGET_BOOTIMAGE_USE_EXT2),true)
$(error TARGET_BOOTIMAGE_USE_EXT2 is not supports anymore)
else ifeq (true, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER))
# 此处省略部分源码 本平台没用到
.....
else ifeq (true, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
# 此处省略部分源码 本平台没用到
.....
else 
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES)
		$(call pretty, "Target boot image: $@")
		for dtsplat in $(TARGET_BOARD_DTS_CONFIG); do 	\
			DTS_PLATFORM=`echo $$dtsplat | cut =d':' -f1`; \
			DTS_BOARD=`echo $$dtsplat | cut =d':' -f2`; \
			BOOT_IMAGE_BOATD=$(patsubst %.img,%-$$DTS_PLATFORM.img,$@);	\
			$(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) --second $(PRODUCT_OUT)/$$DTS_BOARD $(BOARD_MKBOOTIMG_ARGS) --output $@;	\
			cp  -f $@ $$BOOT_IMGAE_BOARD;	\
		done

.PHONY:	bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG)
		@echo "make $@: ignoring dependencies"
		$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET)
		$(hide) $(call assert-max-image-size, $(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
endif
  1. ramdisk 是如何生成的? 跟踪 $(INSTALLED_BOOTIMAGE_TARGET)的依赖 $(INTERNAL_BOOTIMAGE_FILES)
    $(INTERNAL_BOOTIMAGE_FILES) := $(filter-out --%, $(INTERNAL_BOOTIMAGE_ARGS))
    然后有一句:
    $(INTERNAL_BOOTIMAGE_ARGS) += --ramdisk $(INSTALLED_RAMDISK_TARGET)
    所以 $(INSTALLED_RAMDISK_TARGET)会生成ramdisk。
INTERNAL_RAMDISK_FILES := $(filter $(TARGET_ROOT_OUT)/%, \
		$(ALL_PREBUILT)		\
		$(ALL_COPIED_HEADERS)	\
		$(ALL_GENERATED_SOURCES)	\
		$(ALL_DEFAULT_INSTALLED_MODULES))
			
BUILT_RAMDISK_TARGET := $(PRODUCT_OUT)/ramdisk.img

INSTALLED_RAMDISK_TARGET := $(BUILT_RAMDISK_TARGET)
$(INSTALLED_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_RAMDISK_FILES) | $(MINIGZIP)
		$(call pretty, "Target ram disk: $@")
		$(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_ROOT_OUT) | $(MINIGZIP) > $(INSTALLED_RAMDISK_TARGET)

5.目标 bootloader, 即uboot的生成规则。
 bootloader的生成规则相对比较简单,配置好交叉编译器,通过make **defconfig 配置源码,然后 make 就可以,接下来看Makefile:
 build/core/main.mk的默认目标droidcore中包含了 bootloader目标,bootloader目标在build/core/Makefile中有定义:

.PHONY: bootloader
ifneq ($(strip $(TARGET_BOOTLOADER_CONFIG)),)
BOOTLOADER_CROSS_TOOLCHAIN := `pwd`/prebuilts/gcc/linux-x86/arm/arm-linux-androideaib-4.9/bin/arm-linux
BOOTLOADER_ENV	:= ARCH=arm CROSS_COMPILE=$(BOOTLOADER_CROSS_TOOLCHAIN)
HOST_PROCESSOR  := $(shell cat /proc/cpuinfo | grep processor | wc -l)
TARGET_BOOTLODAER_IMAGE := $(PRODUCT_OUT)/u-boot.imx
BOOTLOADER_PATH := bootable/bootloader/uboot/

bootloader: $(TARGET_BOOTLOADER_IMAGE)
.PHONY	$(TARGET_BOOTLOADER_IMAGE)
$(TARGET_BOOTLOADER_IMAGE):
		for ubootplat in $(TARGET_BOOTLOADER_CONFIG); do	\
			UBOOT_PLATFORM=`echo $$ubootplat | cut -d':' -f1`;	\
			UBOOT_CONFIG=`echo $$ubootplat | cut -d':' -f2`;	\
			$(MAKE) -C	$(BOOTLOADER_PATH) distclean $(BOOTLOADER_ENV);	\
			$(MAKE) -C	$(BOOTLOADER_PATH) $$UBOOT_CONFIG $(BOOTLOADER_ENV);	\
			$(MAKE) -C	$(BOOTLOADER_PATH) $(BOOTLOADER_ENV);	\
			install -D	$(BOOTLOADER_PATH)/u-boot.imx $(PRODUCT_OUT)/u-boot-$$UBOOT_PLATFORM.imx; 	\
			install -D	$(BOOTLOADER_PATH)/u-boot.imx $@; 	\
		done
else
bootloader:
endif
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
bootloader.img是一个映像文件,用于引导启动系统。通过查看bootloader.img的二进制内容,可以发现一些信息。根据引用中提到的方法,可以提取官方镜像中的前3841个块,并将其与编译输出的bootloader.img文件连接起来。然后,可以使用刷写脚本代码将新生成的uboot2016.bin文件写入设备中。具体的命令为:sudo dd if=bootloader.img of=uboot2016.bin bs=512 seek=3841和sudo dd if=uboot2016.bin of=/dev/sdx(其中sdx是设备的名称)。 编译过程中,会生成u-boot.bin和bootloader.img两个文件。其中,bootloader.img是一个被签名的uboot映像文件,用于写入Nish参数。这个文件才是最终可以直接用来烧录的uboot编译过程中,会有一个提示,指明了bootloader的生成与tools/nexell/nish/nanopi2.txt文件有关。nanopi2.txt文件配置了一些启动代码和参数,包括uboot的加载地址、加载大小和启动地址等。 总结起来,bootloader.img是一个用于引导启动系统的映像文件。它可以通过提取官方镜像中的一部分内容并与编译输出的bootloader.img文件连接起来生成新的uboot2016.bin文件,然后通过特定的命令将其写入设备中。另外,编译过程中会生成u-boot.bin和bootloader.img两个文件,其中bootloader.img是一个被签名的uboot映像文件,用于写入Nish参数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【NanoPi T2】 2.uboot 离线烧录(S5P4418)](https://blog.csdn.net/qq_16054639/article/details/105829051)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值