环境
# 买了「东山Pi壹号-开发板」,好奇其设备树的编译过程,就了解了一下;
# 使用的 soc 为 SSD202D,sdk 版本为:TAKOYAKI_DLC00V030;
目标 Image 文件生成
# 在 arch/arm/Makefile 中定义了编译目标
BOOT_TARGETS = zImage Image xipImage bootpImage uImage
$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
@$(kecho) ' Kernel: $(boot)/$@ is ready'
# 在 arch/arm/Makefile 中定义了 zImage 的依赖:Image
zImage: Image
# 使用 make V=1 来打印更详细的信息;Makefile 尝试构建 Image 文件;
# 使用 ./scripts/Makefile.build 文件来构建,obj=arch/arm/boot MACHINE 为空,目标为 arch/arm/boot/Image
make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE= arch/arm/boot/Image
# 在 scripts/Makefile.build 中,包含了 arch/arm/boot/Makefile 文件;
# The filename Kbuild has precedence over Makefile
src := $(obj)
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
# 在 scripts/Makefile.build 中,包含了 include scripts/Kbuild.include include scripts/Makefile.lib 文件;
include scripts/Kbuild.include
include scripts/Makefile.lib
# 在 arch/arm/boot/Makefile 中定义了 $(obj)/Image 的依赖:vmlinux;构建生成 Image 文件
$(obj)/Image: vmlinux FORCE
$(call if_changed,objcopy)
目标 dtb 文件生成
# 在 arch/arm/Makefile 中定义了编译目标
BOOT_TARGETS = zImage Image xipImage bootpImage uImage
$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
@$(kecho) ' Kernel: $(boot)/$@ is ready'
# 使用 make V=1 来打印更详细的信息;Makefile 尝试构建 zImage 文件;
# 使用 ./scripts/Makefile.build 文件来构建,obj=arch/arm/boot MACHINE 为空,目标为 arch/arm/boot/zImage
make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE= arch/arm/boot/zImage
# 在 scripts/Makefile.build 中,包含了 arch/arm/boot/Makefile 文件;
# The filename Kbuild has precedence over Makefile
src := $(obj)
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
# 在 scripts/Makefile.build 中,包含了 include scripts/Kbuild.include include scripts/Makefile.lib 文件;
include scripts/Kbuild.include
include scripts/Makefile.lib
# 在 arch/arm/boot/Makefile 中定义了 $(obj)/zImage 的依赖:$(obj)/compressed/vmlinux
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
ifneq ($(CONFIG_ARCH_SSTAR),)
ifeq ($(CONFIG_SS_BUILTIN_DTB), y)
#update builtin DTB
@test "${SS_DTB_NAME}" = "" || \
if [ -e ${SS_DTB_NAME} ]; then \
echo " IMAGE $(obj)/Image"; \
echo " BNDTB ${SS_DTB_NAME}"; \
python scripts/ms_builtin_dtb_update.py $(obj)/Image ${SS_DTB_NAME}; \
echo; \
fi;
#update Image-fpga DTB
@if [ -e "arch/arm/boot/dts/$(CHIP_NAME)-fpga.dtb" ]; then \
echo " IMAGE $(obj)/Image-fpga"; \
cp -f $(obj)/Image $(obj)/Image-fpga; \
echo " BNDTB $(CHIP_NAME)-fpga.dtb"; \
python scripts/ms_builtin_dtb_update.py $(obj)/Image-fpga "arch/arm/boot/dts/$(CHIP_NAME)-fpga.dtb"; \
echo; \
fi;
endif
# 在 arch/arm/boot/Makefile 中定义了 $(obj)/compressed/vmlinux 的依赖:$(obj)/Image $(SS_DTB_NAME) $(MS_EXTRA_DTBS)
$(obj)/compressed/vmlinux: $(obj)/Image FORCE $(SS_DTB_NAME) $(MS_EXTRA_DTBS)
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
# 在 arch/arm/boot/Makefile 中表明了 SS_DTB_NAME=arch/arm/boot/dts/$(_BUILTIN_DTB_NAME).dtb;
# 也就是 .config 文件中的 CONFIG_SS_DTB_NAME="infinity2m-spinand-ssc011a-s01a-display"
_BUILTIN_DTB_NAME=$(strip $(shell echo ${CONFIG_SS_DTB_NAME}))
ifneq ($(_BUILTIN_DTB_NAME),)
ifneq ($(wildcard arch/arm/boot/dts/$(_BUILTIN_DTB_NAME).dts),)
SS_DTB_NAME=arch/arm/boot/dts/$(_BUILTIN_DTB_NAME).dtb
endif
endif
# 在 ./scripts/Makefile.lib 中,定义了 dtb 的目标;使用 dtc 函数来构建 dtb 文件;
# quiet_cmd_ 和 cmd_ 为 Makefile 的命令格式;quiet_cmd_ 为隐式输出
quiet_cmd_dtc = DTC $@
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
$(DTC) -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
$(obj)/%.dtb: $(src)/%.dts FORCE
$(call if_changed_dep,dtc)
将 dtb 写入 Image 文件
# 在 arch/arm/boot/Makefile 中定义了 $(obj)/zImage 的依赖:$(obj)/compressed/vmlinux
# 构建目标后执行了 python scripts/ms_builtin_dtb_update.py $(obj)/Image-fpga "arch/arm/boot/dts/$(CHIP_NAME)-fpga.dtb";
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
ifneq ($(CONFIG_ARCH_SSTAR),)
ifeq ($(CONFIG_SS_BUILTIN_DTB), y)
#update builtin DTB
@test "${SS_DTB_NAME}" = "" || \
if [ -e ${SS_DTB_NAME} ]; then \
echo " IMAGE $(obj)/Image"; \
echo " BNDTB ${SS_DTB_NAME}"; \
python scripts/ms_builtin_dtb_update.py $(obj)/Image ${SS_DTB_NAME}; \
echo; \
fi;
#update Image-fpga DTB
@if [ -e "arch/arm/boot/dts/$(CHIP_NAME)-fpga.dtb" ]; then \
echo " IMAGE $(obj)/Image-fpga"; \
cp -f $(obj)/Image $(obj)/Image-fpga; \
echo " BNDTB $(CHIP_NAME)-fpga.dtb"; \
python scripts/ms_builtin_dtb_update.py $(obj)/Image-fpga "arch/arm/boot/dts/$(CHIP_NAME)-fpga.dtb"; \
echo; \
fi;
endif
# ms_builtin_dtb_update.py 文件内容如下:
# 使用`#!/usr/bin/python`指定解释器路径
#!/usr/bin/python
# 导入了几个需要的模块,包括`re`(正则表达式处理)、`fnmatch`(文件名匹配)、`os`(操作系统功能接口)、`sys`(Python运行时环境)、`mmap`(内存映射文件支持)和`struct`(C结构体样式的数据转换)。
import re, fnmatch, os, sys, mmap, struct
if __name__ == '__main__':
name='#MS_DTB#'
# 从命令行参数中取得DTB文件路径(`sys.argv[2]`)。
# 打开文件,并读取其大小和内容。
dtb_file=open(sys.argv[2])
dtb_file.seek(0,os.SEEK_END)
size=dtb_file.tell()
dtb_file.seek(0,os.SEEK_SET)
dtb=dtb_file.read()
dtb_file.close()
# 如果DTB的大小超过64KB,打印一个错误消息并退出。
if sys.getsizeof(dtb) > (64*1024):
print ('DTB size 0x%08X too big to fit in 64K limit!!' % dtb.size())
sys.exit()
# 打开一个文件(`sys.argv[1]`)以读/写模式,并对其进行内存映射。
fmap=mmap.mmap(os.open(sys.argv[1],os.O_RDWR),0)
# 在该映射文件中查找`#MS_DTB#`标记。
offset=fmap.find(name)
# 如果成功找到`#MS_DTB#`标记
# 打印找到的偏移位置。
# 将文件指针移到标记后的8个字节,并写入DTB的大小(使用小端格式)。
# 将文件指针移到标记后的16个字节,并写入整个DTB内容。
if offset >=0:
print ('offset:0x%08X' % offset)
print (' size:0x%08X' % size )
fmap.seek(offset + 8, os.SEEK_SET)
fmap.write(struct.pack('<I', size))
fmap.seek(offset + 16, os.SEEK_SET)
fmap.write(dtb)
fmap.close()
# "#MS_DTB#" 标记在文件 arch/arm/mach-sstar/ms_chip.c 中定义,并开辟了一个 64k 的数组空间在 Image 中;
#ifdef CONFIG_SS_BUILTIN_DTB
#define BUILTIN_DTB_SZ (64*1024)
struct MS_BUILTIN_DTB
{
struct MS_BIN_OPTION ms_dtb;
u8 content[BUILTIN_DTB_SZ];
};
struct MS_BUILTIN_DTB builtin_dtb __attribute__ ((aligned (16)))=
{
.ms_dtb={ {'#','M','S','_','D','T','B','#'}, {0,0,0,0,0,0,0,0}},
};
void *builtin_dtb_start=(void *)builtin_dtb.content;
const u32 builtin_dtb_size=BUILTIN_DTB_SZ;
#endif
# 在 arch/arm/boot/Makefile 中,将 Image 文件压缩,添加 uboot 头,成 uImage.xz 文件;
#update the image size into Image
@python scripts/ms_bin_option_update_int.py $(obj)/Image '#IMG_SZ#' $$(stat -c %s $(obj)/Image)
#build Image
@IMGNAME=$(shell strings -a -T binary $(obj)/Image | grep 'MVX' | grep 'LX' | sed 's/\\*MVX/MVX/g' | cut -c 1-32 ); \
if [ -e ${MKIMAGE_BIN} ]; then \
${MKIMAGE_BIN} -A arm -O linux -T kernel -C none -a ${LD_ADDR} -e ${LD_ADDR} -n $${IMGNAME} -d $(obj)/Image $(obj)/uImage; \
echo; \
echo 'Compress Kernel Image'; \
xz -z -k -f $(obj)/Image; \
${MKIMAGE_BIN} -A arm -O linux -C lzma -a ${LD_ADDR} -e ${LD_ADDR} -n $${IMGNAME} -d $(obj)/Image.xz $(obj)/uImage.xz; \
${MZ_BIN} c $(obj)/Image $(obj)/Image.mz ; \
echo; \
${MKIMAGE_BIN} -A arm -O linux -C mz -a ${LD_ADDR} -e ${LD_ADDR} -n $${IMGNAME} -d $(obj)/Image.mz $(obj)/uImage.mz; \
echo; \
else \
echo ">> Can't find $${MKIMAGE}. Please check the u-boot path or build u-boot <<"; \
fi; \
# project 中的 kernel 文件应该就是 uImage.xz 重命名文件;
# 将其烧录进 spi flash 的 KERNEL 分区就行;