代码改变世界

uImage编译生成流程分析

2019-08-04 22:41  在路上啊  阅读(584)  评论(0)    收藏  举报

uImage的编译生成 参考资料 : linux-4.0.0 + arm架构

1. vmlinux的生成
--->Makefile

init-y := init/

drivers-y := drivers/ sound/ firmware/
net-y := net/
libs-y := lib/
core-y := usr/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
$(net-y) $(net-m) $(libs-y) $(libs-m)))
vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
$(init-) $(core-) $(drivers-) $(net-) $(libs-))))
# Externally visible symbols (used by link-vmlinux.sh)
export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y)
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
结论:
vmlinux是根据arch/arm/kernel/vmlinux.lds链接以下目录下的.o文件而生成
vmlinux = arch/arm/kernel/head.o init/ usr/ kernel/ mm/ fs/ ipc/ security/ crypto/ block/ lib/ drivers/ sound/ firmware/ net/

2. 用vmlinux去除调试信息和符号生成arch/arm/boot/Image
---> arch/arm/boot/Makefile
OBJCOPYFLAGS :=-O binary -R .comment -S
$(obj)/Image: vmlinux FORCE
$(call if_changed,objcopy) # 1. 用ojbcopy去掉符号
@$(kecho) ' Kernel: $@ is ready'

3. 用arch/arm/boot/Image进一步生成arch/arm/boot/compressed/vmlinux
---> arch/arm/boot/compressed/Makefile
suffix_$(CONFIG_KERNEL_GZIP) = gzip

$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE # 1. 将arch/arm/boot/Image 用gzip压成piggy.gzip
$(call if_changed,$(suffix_y))

$(obj)/piggy.$(suffix_y).o: $(obj)/piggy.$(suffix_y) FORCE # 2. piggy.gzip.S + piggy.gzip, 生成piggy.gzip.o

$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
$(bswapsdi2) FORCE
@$(check_for_multiple_zreladdr)
$(call if_changed,ld)
@$(check_for_bad_syms)

结论 : arch/arm/boot/compressed/vmlinux是根据 arch/arm/boot/compressed/vmlinux.lds进行链接生成的
arch/arm/boot/compressed/vmlinux = arch/arm/boot/compressed/head.o + misc.o + piggy.gzip.o

4. 用arch/arm/boot/compressed/vmlinux生成arch/arm/boot/zImage
---> arch/arm/boot/Makefile
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@$(kecho) ' Kernel: $@ is ready'

5. 用arch/arm/boot/zImage生成arch/arm/boot/uImage
---> arch/arm/boot/Makefile
$(obj)/uImage: $(obj)/zImage FORCE
@$(check_for_multiple_loadaddr)
$(call if_changed,uimage) # 1. cmd_uimage命令 uImage = 64字节头部 + zImage
@$(kecho) ' Image $@ is ready'

MISC. 过程关联脚本
---> scripts/kbuild.include
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)

---> scripts/makefile.lib
quiet_cmd_objcopy = OBJCOPY $@
cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@

quiet_cmd_uimage = UIMAGE $(UIMAGE_OUT)
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \
-C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \
-T $(UIMAGE_TYPE) \
-a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \
-n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT)