zoukankan      html  css  js  c++  java
  • uboot makefile构建分析-续

    前言

      这篇博文是 uboot makefile构建分析的续篇,继续分析uboot构建u-boot.bin的过程

    构建u-boot.bin过程分析

      makefile一开始,就是确定链接脚本。在构建uboot和kernel的过程,链接脚本是非常重要的。它决定了你程序里面每个段的位置(加载位置和运行位置)。在编译应用程序时,我们一般不需要指定链接脚本,因为链接器这时候会采用默认的,通过命令ld --verbose可以查看默认的链接脚本。之所以uboot和kernel不采用默认的,是因为它们有特殊要求,比如要求哪些部分必须放在最前面,哪些部分放在哪个地址上等等。下面看uboot寻找链接脚本的代码(直接将说明插入到代码了):

    LDSCRIPT_MAKEFILE_DIR = $(dir $(LDSCRIPT))                                      
                                                                                    
    ifndef LDSCRIPT  #如果没有指定LDSCRIPT                                                               
        #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug                   
        ifdef CONFIG_SYS_LDSCRIPT #如果指定了CONFIG_SYS_LDSCRIPT,那么LDSCRIPT就用CONFIG_SYS_LDSCRIPT指定的作为链接脚本
            # need to strip off double quotes                                       
            LDSCRIPT := $(subst ",,$(CONFIG_SYS_LDSCRIPT))                          
        endif                                                                       
    endif                                                                           
                                                                                    
    # If there is no specified link script, we look in a number of places for it    
    ifndef LDSCRIPT  #如果还没指定LDSCRIPT(也就是板级没有指定CONFIG_SYS_LDSCRIPT,那么只好根据构建的方式自己采用默认的了
        ifeq ($(CONFIG_NAND_U_BOOT),y) #如果是nand boot模式                                             
            LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds                 
            ifeq ($(wildcard $(LDSCRIPT)),)#如果board/$(BOARDDIR)/u-boot-nand.lds不存在,用$(CPUDIR)/u-boot-nand.lds                                         
                LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds                     
            endif                                                                   
        endif                                                                       
        ifeq ($(wildcard $(LDSCRIPT)),) #如果nand对应的lds文件不存在,用board/$(BOARDDIR)/u-boot.lds                                            
            LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds                      
        endif                                                                       
        ifeq ($(wildcard $(LDSCRIPT)),) #如果对应的lds文件还不存在,用$(CPUDIR)/u-boot.lds                                            
            LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot.lds                              
        endif                                                                       
        ifeq ($(wildcard $(LDSCRIPT)),) ##如果对应的文件还不存在,用arch/$(ARCH)/cpu/u-boot.lds                                            
            LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot.lds                       
            # We don't expect a Makefile here                                       
            LDSCRIPT_MAKEFILE_DIR =                                                 
        endif                                                                       
        ifeq ($(wildcard $(LDSCRIPT)),)                                             
    $(error could not find linker script)                                           
        endif                                                                       
    endif  
    

    如果板子有自己对应的链接脚本,不需要通用的,那么可以通过配置LDSCRIPT或者CONFIG_SYS_LDSCRIPT来实现。从上一篇博文 uboot makefile构建分析可以知道,该头文件会在执行第二步配置的时候,会被包含到config.h里。下面是我这个uboot版本里有添加这些宏的板子:

    $ grep -rns CONFIG_SYS_LDSCRIPT include/
    include/configs/actux2.h:27:#define CONFIG_SYS_LDSCRIPT	"board/actux2/u-boot.lds"
    include/configs/MPC8569MDS.h:60:#define CONFIG_SYS_LDSCRIPT $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds
    include/configs/BSC9131RDB.h:45:#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
    include/configs/actux1.h:27:#define CONFIG_SYS_LDSCRIPT	"board/actux1/u-boot.lds"
    include/configs/mpq101.h:168:#define CONFIG_SYS_LDSCRIPT     "board/mercury/mpq101/u-boot.lds"
    include/configs/MVBLUE.h:31:#define CONFIG_SYS_LDSCRIPT	"board/mvblue/u-boot.lds"
    include/configs/p1_p2_rdb_pc.h:201:#define CONFIG_SYS_LDSCRIPT		"arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
    include/configs/MVSMR.h:22:#define CONFIG_SYS_LDSCRIPT	"board/matrix_vision/mvsmr/u-boot.lds"
    include/configs/sh7757lcr.h:21:#define CONFIG_SYS_LDSCRIPT	"board/renesas/sh7757lcr/u-boot.lds"
    include/configs/MPC8572DS.h:27:#define CONFIG_SYS_LDSCRIPT $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds
    include/configs/am335x_evm.h:29:#define CONFIG_SYS_LDSCRIPT		"board/ti/am335x/u-boot.lds"
    include/configs/Sandpoint8240.h:27:#define CONFIG_SYS_LDSCRIPT	"board/sandpoint/u-boot.lds"
    include/configs/P1023RDS.h:29:#define CONFIG_SYS_LDSCRIPT $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds
    include/configs/P1022DS.h:40:#define CONFIG_SYS_LDSCRIPT		"arch/powerpc/cpu/mpc85xx/u-boot.lds"
    include/configs/P1022DS.h:70:#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc85xx/u-boot.lds"
    include/configs/P1022DS.h:117:#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
    include/configs/P1010RDB.h:53:#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
    include/configs/rsdproto.h:27:#define	CONFIG_SYS_LDSCRIPT	"board/rsdproto/u-boot.lds"
    include/configs/uc101.h:22:#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds"
    include/configs/MOUSSE.h:37:#define	CONFIG_SYS_LDSCRIPT	"board/mousse/u-boot.lds"
    include/configs/actux3.h:27:#define CONFIG_SYS_LDSCRIPT	"board/actux3/u-boot.lds"
    include/configs/dvlhost.h:28:#define CONFIG_SYS_LDSCRIPT	"board/dvlhost/u-boot.lds"
    include/configs/EVB64260.h:30:#define	CONFIG_SYS_LDSCRIPT	"board/evb64260/u-boot.lds"
    include/configs/CATcenter.h:66:#define CONFIG_SYS_LDSCRIPT	"board/dave/PPChameleonEVB/u-boot.lds"
    include/configs/PPChameleonEVB.h:66:#define CONFIG_SYS_LDSCRIPT	"board/dave/PPChameleonEVB/u-boot.lds"
    include/configs/MPC8536DS.h:27:#define CONFIG_SYS_LDSCRIPT $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds
    include/configs/inka4x0.h:31:#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds"
    include/configs/BSC9132QDS.h:54:#define CONFIG_SYS_LDSCRIPT	"arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
    include/configs/sh7752evb.h:20:#define CONFIG_SYS_LDSCRIPT	"board/renesas/sh7752evb/u-boot.lds"
    include/configs/P1_P2_RDB.h:41:#define CONFIG_SYS_LDSCRIPT $(TOPDIR)/$(CPUDIR)/u-boot-nand.lds
    include/configs/Sandpoint8245.h:27:#define CONFIG_SYS_LDSCRIPT	"board/sandpoint/u-boot.lds"
    
    

    我这里假设板级没有指定LDSCRIPT或者CONFIG_SYS_LDSCRIPT,也不是nand boot模式,board/$(BOARDDIR)和$(CPUDIR)/u-boot.lds下也没有lds文件,那么就用arch/$(ARCH)/cpu/u-boot.lds了(即arch/arm/cpu/u-boot.lds),因为该文件默认就存在。

    下面看all目标,因为该目标而导致最终的u-boot.bin被构建出来

    # Always append ALL so that arch config.mk's can add custom ones                
    ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map 
    
    all:        $(ALL-y) $(SUBDIR_EXAMPLES)  
    

    从上面可知,首先构建u-boot.srec,然后是u-boot.bin,下面重点看u-boot.bin的构建过程,至于u-boot.srec(u-boot.srec是Motorola S-Record格式的image文件,我是从来没用过)和System.map(该文件按链接地址由小到大的顺序列出了所有符号,一般用于调试),就忽略吧,u-boot.bin的规则如下:

    $(obj)u-boot.bin:   $(obj)u-boot                                                
            $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@                                 
            $(BOARD_SIZE_CHECK)   
    

    依赖u-boot,于是看u-boot

    $(obj)u-boot:   depend                                                         
            $(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
            $(GEN_UBOOT)                                                            
    ifeq ($(CONFIG_KALLSYMS),y)                                                     
            smap=`$(call SYSTEM_MAP,$(obj)u-boot) |                                
                awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\000"}'` ;                 
            $(CC) $(CFLAGS) -DSYSTEM_MAP=""$${smap}""                            
                -c common/system_map.c -o $(obj)common/system_map.o                 
            $(GEN_UBOOT) $(obj)common/system_map.o                                  
    endif 
    

    u-boot依赖一堆,它也是uboot构建主要要做的事情。从这里我们可以知道uboot的构建就是先构建u-boot,然后再生成u-boot.bin。下面继续看u-boot的每一个依赖吧

    第一个依赖depend

    depend dep: $(TIMESTAMP_FILE) $(VERSION_FILE)                                  
            $(obj)include/spl-autoconf.mk                                          
            $(obj)include/tpl-autoconf.mk                                          
            $(obj)include/autoconf.mk                                              
            $(obj)include/generated/generic-asm-offsets.h                          
            $(obj)include/generated/asm-offsets.h                                   
            for dir in $(SUBDIRS) $(CPUDIR) $(LDSCRIPT_MAKEFILE_DIR) ; do          
                $(MAKE) -C $$dir _depend ; done 
    

    忽略分析它的依赖吧,大部分在执行第二步配置的时候生成的。还一些文件是用于辅佐构建的。直接看命令部分,其中

    ifeq ($(wildcard $(LDSCRIPT)),)                                             
            LDSCRIPT := $(TOPDIR)/arch/$(ARCH)/cpu/u-boot.lds                       
            # We don't expect a Makefile here                                       
            LDSCRIPT_MAKEFILE_DIR =                                                 
    endif 
    LDSCRIPT_MAKEFILE_DIR = $(dir $(LDSCRIPT))
    
    SUBDIRS = $(SUBDIR_TOOLS)
    ifndef CONFIG_SANDBOX                                                           
    SUBDIRS += $(SUBDIR_EXAMPLES)                                                   
    endif
    
    CPUDIR=arch/$(ARCH)/cpu/$(CPU)
    

    因此,depend会去这些目录(也就是目录tools [examples/standalone、examples/api] arch/arm/cpu/armv7/)执行_depend目标

    第二个依赖SUBDIR_TOOLS

    SUBDIR_TOOLS = tools
    SUBDIR_EXAMPLES = examples/standalone examples/api                              
    SUBDIRS = $(SUBDIR_TOOLS)
    ifndef CONFIG_SANDBOX                                                           
    SUBDIRS += $(SUBDIR_EXAMPLES)                                                   
    endif
    $(SUBDIRS): depend                                                              
            $(MAKE) -C $@ all
    

    去tools目录下执行all目标。之所以要这么早构建tools下的程序,是因为后面的构建过程会用到它们。

    第三个依赖OBJS

    $(OBJS):    depend                                                              
            $(MAKE) -C $(CPUDIR) $(if $(REMOTE_BUILD),$@,$(notdir $@)) 
    

    开始执行OBJS里面指定的文件了

    OBJS  = $(CPUDIR)/start.o                                                       
    ifeq ($(CPU),ppc4xx)                                                            
    OBJS += $(CPUDIR)/resetvec.o                                                    
    endif                                                                           
    ifeq ($(CPU),mpc85xx)                                                           
    OBJS += $(CPUDIR)/resetvec.o                                                    
    endif                                                                           
                                                                                    
    OBJS := $(addprefix $(obj),$(OBJS))  
    

    其实就是构建arch/arm/cpu/armv7/start.o(当然是根据arch/arm/cpu/armv7/start.S啦)

    第四个依赖LIBBOARD

    $(LIBBOARD):    depend $(LIBS)                                                  
            $(MAKE) -C $(dir $(subst $(obj),,$@))  
    
    

    开始执行LIBBOARD里指定的文件了。注意,它依赖LIBS,也就是说第五个依赖会先执行。

    BOARD  = zynq                                                                   
    VENDOR = xilinx 
    
    ifdef   VENDOR                                                                  
    BOARDDIR = $(VENDOR)/$(BOARD)                                                   
    else                                                                            
    BOARDDIR = $(BOARD)                                                             
    endif  
    
    LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).o                                      
    LIBBOARD := $(addprefix $(obj),$(LIBBOARD))
    

    最终就是构建board/$(BOARDDIR)/下的默认目标,我这里就是board/xilinx/zynq/Makefile,对应的它里面的规则:

    LIB = $(obj)lib$(BOARD).o                                                       
                                                                                    
    COBJS-y := board.o                                                              
                                                                                    
    # Added by MYIR for MYS-XC7Z010                                                 
    COBJS-y += myir_init.o                                                          
                                                                                    
    COBJS   := $(sort $(COBJS-y))                                                   
                                                                                    
    SRCS    := $(COBJS:.o=.c)                                                       
    OBJS    := $(addprefix $(obj),$(COBJS)) 
    
    $(LIB): $(obj).depend $(OBJS)                                                   
        $(call cmd_link_o_target, $(OBJS)) 
    

    第五个依赖LIBS

    $(LIBS):    depend $(SUBDIR_TOOLS)                                              
            $(MAKE) -C $(dir $(subst $(obj),,$@)) 
    

    开始执行LIBS里指定的文件了,到这一步,它的依赖在前面都执行完了,直接看LIBS有哪些吧!

    LIBS-y += lib/libgeneric.o                                                      
    LIBS-y += lib/rsa/librsa.o                                                      
    LIBS-y += lib/lzma/liblzma.o                                                    
    LIBS-y += lib/lzo/liblzo.o                                                      
    LIBS-y += lib/zlib/libz.o                                                       
    LIBS-$(CONFIG_TIZEN) += lib/tizen/libtizen.o                                    
    LIBS-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/lib$(VENDOR).o         
    LIBS-y += $(CPUDIR)/lib$(CPU).o                                                 
    ifdef SOC                                                                       
    LIBS-y += $(CPUDIR)/$(SOC)/lib$(SOC).o                                          
    endif                                                                           
    ifeq ($(CPU),ixp)                                                               
    LIBS-y += drivers/net/npe/libnpe.o                                              
    endif                                                                           
    LIBS-$(CONFIG_OF_EMBED) += dts/libdts.o                                         
    LIBS-y += arch/$(ARCH)/lib/lib$(ARCH).o                                         
    LIBS-y += fs/libfs.o                                                           
        fs/cbfs/libcbfs.o                                                          
        fs/cramfs/libcramfs.o                                                      
        fs/ext4/libext4fs.o                                                        
        fs/fat/libfat.o                                                            
        fs/fdos/libfdos.o                                                          
        fs/jffs2/libjffs2.o                                                        
        fs/reiserfs/libreiserfs.o                                                  
        fs/sandbox/libsandboxfs.o                                                  
        fs/ubifs/libubifs.o                                                        
        fs/yaffs2/libyaffs2.o                                                      
        fs/zfs/libzfs.o                                                             
    LIBS-y += net/libnet.o                                                          
    LIBS-y += disk/libdisk.o                                                        
    LIBS-y += drivers/bios_emulator/libatibiosemu.o                                 
    LIBS-y += drivers/block/libblock.o                                              
    LIBS-$(CONFIG_BOOTCOUNT_LIMIT) += drivers/bootcount/libbootcount.o              
    LIBS-y += drivers/crypto/libcrypto.o                                            
    LIBS-y += drivers/dma/libdma.o                                                  
    LIBS-y += drivers/fpga/libfpga.o  
    LIBS-y += drivers/gpio/libgpio.o                                                
    LIBS-y += drivers/hwmon/libhwmon.o                                              
    LIBS-y += drivers/i2c/libi2c.o                                                  
    LIBS-y += drivers/input/libinput.o                                              
    LIBS-y += drivers/misc/libmisc.o                                                
    LIBS-y += drivers/mmc/libmmc.o                                                  
    LIBS-y += drivers/mtd/libmtd.o                                                  
    LIBS-y += drivers/mtd/nand/libnand.o                                            
    LIBS-y += drivers/mtd/onenand/libonenand.o                                      
    LIBS-y += drivers/mtd/ubi/libubi.o                                              
    LIBS-y += drivers/mtd/spi/libspi_flash.o                                        
    LIBS-y += drivers/net/libnet.o                                                  
    LIBS-y += drivers/net/phy/libphy.o                                              
    LIBS-y += drivers/pci/libpci.o                                                  
    LIBS-y += drivers/pcmcia/libpcmcia.o                                            
    LIBS-y += drivers/power/libpower.o                                             
        drivers/power/fuel_gauge/libfuel_gauge.o                                   
        drivers/power/mfd/libmfd.o                                                 
        drivers/power/pmic/libpmic.o                                               
        drivers/power/battery/libbattery.o                                          
    LIBS-y += drivers/spi/libspi.o                                                  
    LIBS-y += drivers/dfu/libdfu.o                                                  
    ifeq ($(CPU),mpc83xx)                                                           
    LIBS-y += drivers/qe/libqe.o                                                    
    LIBS-y += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o                                 
    LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o                                    
    endif                                                                           
    ifeq ($(CPU),mpc85xx)                                                           
    LIBS-y += drivers/qe/libqe.o                                                    
    LIBS-y += drivers/net/fm/libfm.o         
    LIBS-y += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o                                 
    LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o                                    
    endif                                                                           
    ifeq ($(CPU),mpc86xx)                                                           
    LIBS-y += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o                                 
    LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o                                    
    endif                                                                           
    LIBS-y += drivers/rtc/librtc.o                                                  
    LIBS-y += drivers/serial/libserial.o                                            
    LIBS-y += drivers/sound/libsound.o                                              
    LIBS-y += drivers/tpm/libtpm.o                                                  
    LIBS-y += drivers/twserial/libtws.o                                             
    LIBS-y += drivers/usb/eth/libusb_eth.o                                          
    LIBS-y += drivers/usb/gadget/libusb_gadget.o                                    
    LIBS-y += drivers/usb/host/libusb_host.o                                        
    LIBS-y += drivers/usb/musb/libusb_musb.o                                        
    LIBS-y += drivers/usb/musb-new/libusb_musb-new.o                                
    LIBS-y += drivers/usb/phy/libusb_phy.o                                          
    LIBS-y += drivers/usb/ulpi/libusb_ulpi.o                                        
    LIBS-y += drivers/video/libvideo.o                                              
    LIBS-y += drivers/watchdog/libwatchdog.o                                        
    LIBS-y += common/libcommon.o                                                    
    LIBS-y += lib/libfdt/libfdt.o                                                   
    LIBS-y += api/libapi.o                                                          
    LIBS-y += post/libpost.o                                                        
    LIBS-y += test/libtest.o                                                        
                                                                                    
    ifneq ($(CONFIG_OMAP_COMMON),)                                                  
    LIBS-y += $(CPUDIR)/omap-common/libomap-common.o                                
    endif                                                                           
                                                                                    
    ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx31 mx35 mxs vf610))                
    LIBS-y += arch/$(ARCH)/imx-common/libimx-common.o                               
    endif            
                                                                                    
    ifeq ($(SOC),s5pc1xx)                                                           
    LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o                                  
    endif                                                                           
    ifeq ($(SOC),exynos)                                                            
    LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o                                  
    endif                                                                           
    ifneq ($(CONFIG_TEGRA),)                                                        
    LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o                     
    LIBS-y += arch/$(ARCH)/cpu/tegra-common/libcputegra-common.o                    
    LIBS-y += $(CPUDIR)/tegra-common/libtegra-common.o                              
    endif                                                                           
                                                                                    
    LIBS := $(addprefix $(obj),$(sort $(LIBS-y)))                                   
    .PHONY : $(LIBS)                                        
    

    看到它,大概也猜到了,大部分文件的编译都在这。

    第六个依赖LDSCRIPT

    $(LDSCRIPT):    depend                                                          
            $(MAKE) -C $(dir $@) $(notdir $@)
    

    LDSCRIPT在寻找链接脚本时,我这里的LDSCRIPT已经假设为arch/$(ARCH)/cpu/u-boot.lds了(即arch/arm/cpu/u-boot.lds)。它的命令就是去arch/arm/cpu下执行u-boot.lds目标啦,但是我发现那目录下根本没有makefile!

    第七个依赖u-boot.lds

    $(obj)u-boot.lds: $(LDSCRIPT)                                                   
            $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$< >$@ 
    

    对应我这里的命令:

    arm-xilinx-linux-gnueabi-gcc -E -g  -Os   -ffunction-sections -fdata-sections -fno-common -ffixed-r8 -msoft-float  -fno-strict-aliasing -mno-unaligned-access -D__KERNEL__ -DCONFIG_SYS_TEXT_BASE=0x04000000 -I/home/rongp/company/zynq/Bootloader/u-boot-xlnx/include -fno-builtin -ffreestanding -nostdinc -isystem /home/rongp/company/zynq/Toolchain/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/../lib/gcc/arm-xilinx-linux-gnueabi/4.6.1/include -pipe  -DCONFIG_ARM -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -mword-relocations -march=armv7-a -include /home/rongp/company/zynq/Bootloader/u-boot-xlnx/include/u-boot/u-boot.lds.h -DCPUDIR=arch/arm/cpu/armv7  -ansi -D__ASSEMBLY__ -P - </home/rongp/company/zynq/Bootloader/u-boot-xlnx/arch/arm/cpu/u-boot.lds >u-boot.lds
    

    分析完依赖

    $(obj)u-boot:   depend                                                         
            $(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds
            $(GEN_UBOOT) 
    

    ,下面继续看u-boot对应的命令部分

            $(GEN_UBOOT)                                                                                                                          
    ifeq ($(CONFIG_KALLSYMS),y)  #这部分部分析,忽略                                                   
            smap=`$(call SYSTEM_MAP,$(obj)u-boot) |                                
                awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\000"}'` ;                 
            $(CC) $(CFLAGS) -DSYSTEM_MAP=""$${smap}""                            
                -c common/system_map.c -o $(obj)common/system_map.o                 
            $(GEN_UBOOT) $(obj)common/system_map.o                                  
    endif 
    

    其中GEN_UBOOT定义如下:

    ifeq ($(CONFIG_SANDBOX),y)                                                      
    GEN_UBOOT =                                                                    
            cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds                       
                -Wl,--start-group $(__LIBS) -Wl,--end-group                        
                $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map -o u-boot                  
    else                                                                            
    GEN_UBOOT =                                                                    
            cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F))                       
                $(__OBJS)                                                          
                --start-group $(__LIBS) --end-group $(PLATFORM_LIBS)               
                -Map u-boot.map -o u-boot                                           
    endif  
    

    对应我这里的命令:

    cd /home/rongp/company/zynq/Bootloader/u-boot-xlnx && arm-xilinx-linux-gnueabi-ld  -pie -T u-boot.lds --gc-sections -Bstatic -Ttext 0x04000000 arch/arm/cpu/armv7/start.o --start-group api/libapi.o arch/arm/cpu/armv7/libarmv7.o arch/arm/cpu/armv7/zynq/libzynq.o arch/arm/lib/libarm.o common/libcommon.o disk/libdisk.o drivers/bios_emulator/libatibiosemu.o drivers/block/libblock.o drivers/crypto/libcrypto.o drivers/dfu/libdfu.o drivers/dma/libdma.o drivers/fpga/libfpga.o drivers/gpio/libgpio.o drivers/hwmon/libhwmon.o drivers/i2c/libi2c.o drivers/input/libinput.o drivers/misc/libmisc.o drivers/mmc/libmmc.o drivers/mtd/libmtd.o drivers/mtd/nand/libnand.o drivers/mtd/onenand/libonenand.o drivers/mtd/spi/libspi_flash.o drivers/mtd/ubi/libubi.o drivers/net/libnet.o drivers/net/phy/libphy.o drivers/pci/libpci.o drivers/pcmcia/libpcmcia.o drivers/power/battery/libbattery.o drivers/power/fuel_gauge/libfuel_gauge.o drivers/power/libpower.o drivers/power/mfd/libmfd.o drivers/power/pmic/libpmic.o drivers/rtc/librtc.o drivers/serial/libserial.o drivers/sound/libsound.o drivers/spi/libspi.o drivers/tpm/libtpm.o drivers/twserial/libtws.o drivers/usb/eth/libusb_eth.o drivers/usb/gadget/libusb_gadget.o drivers/usb/host/libusb_host.o drivers/usb/musb-new/libusb_musb-new.o drivers/usb/musb/libusb_musb.o drivers/usb/phy/libusb_phy.o drivers/usb/ulpi/libusb_ulpi.o drivers/video/libvideo.o drivers/watchdog/libwatchdog.o fs/cbfs/libcbfs.o fs/cramfs/libcramfs.o fs/ext4/libext4fs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o fs/libfs.o fs/reiserfs/libreiserfs.o fs/sandbox/libsandboxfs.o fs/ubifs/libubifs.o fs/yaffs2/libyaffs2.o fs/zfs/libzfs.o lib/libfdt/libfdt.o lib/libgeneric.o lib/lzma/liblzma.o lib/lzo/liblzo.o lib/rsa/librsa.o lib/zlib/libz.o net/libnet.o post/libpost.o test/libtest.o board/xilinx/zynq/libzynq.o --end-group /home/rongp/company/zynq/Bootloader/u-boot-xlnx/arch/arm/lib/eabi_compat.o  -L /home/rongp/company/zynq/Toolchain/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/../lib/gcc/arm-xilinx-linux-gnueabi/4.6.1 -lgcc -Map u-boot.map -o u-boot
    

    u-boot是ELF格式二进制的image文件,u-boot.bin是原始的二进制image文件。构建完u-boot,接着就是构建uboot.bin了:

    $(obj)u-boot.bin:   $(obj)u-boot                                                
            $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@                                 
            $(BOARD_SIZE_CHECK)   
    

    对应我这里的命令:

    arm-xilinx-linux-gnueabi-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
    

    all目标还会构建SUBDIR_EXAMPLES,它对应的规则:

    ifndef CONFIG_SANDBOX                                                           
    SUBDIRS += $(SUBDIR_EXAMPLES)                                                   
    endif  
    
    $(SUBDIRS): depend                                                              
            $(MAKE) -C $@ all
    

    链接脚本分析

    最后再分析下链接脚本吧!先贴出我这里使用到的arch/arm/cpu/u-boot.lds(说明直接嵌入到脚本中):

    /*
     * Copyright (c) 2004-2008 Texas Instruments
     *
     * (C) Copyright 2002
     * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    
    OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")//三个分别指定在缺省、大端、小端情况下的输出可执行文件格式,这里都指定输出格式是elf32,小端和arm体系结构
    OUTPUT_ARCH(arm)//输出可执行文件指定为arm体系结构
    ENTRY(_start)//指定_start函数为程序的入口。_start在每个CPU目录下的start.S中定义,真正的启动运行地址段由CONFIG_SYS_TEXT_BASE宏定义在编译时由config.mk中定义
    SECTIONS //每个链接脚本都会有一个SECTIONS,它里面会有很多section用于描述每个段最终存放到输出文件的位置。The SECTIONS command tells the linker how to map input sections into output sections, and how to place the output sections in memory.
    {
    	. = 0x00000000;//指定定位器符号为0,定系统启动从偏移地址零处开始。
    //注意这只是个代码地址偏移值,真正的起始地址是由编译时指定的LDFLAGS_XXX指定的
    
    	. = ALIGN(4);//4字节对齐
    	.text ://这里指定所有文件的.__image_copy_start以及CPUDIR/start.o的.text*以及所有其他文件的.text*都放到.text段
    	{
    		*(.__image_copy_start)//u-boot将自己copy到RAM,此为需要copy的程序的start,参考arch/arm/lib/sections.c和arch/arm/lib/relocate.S
    		CPUDIR/start.o (.text*)//对应到我这里,就是arch/arm/cpu/armv7/start.o文件啦
    		*(.text*)//其他所有文件的.text*
    	}
    
    	. = ALIGN(4);//修改当前定位寄存器,保持4字节对齐
    	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }//指定所有文件的.rodata*放到.rodata段,
    //放置前先用SORT_BY_NAME排序,然后用SORT_BY_ALIGNMENT做排序,SORT_BY_ALIGNMENT会根据对齐的
    //特性进行降序排序,The difference is SORT_BY_ALIGNMENT will sort sections into descending order by alignment 
    //before placing them in the output file. Larger alignments are placed before 
    //smaller alignments in order to reduce the amount of padding necessary. 
    //在代码段之后,存放read only数据段
    
    	. = ALIGN(4);//修改当前定位寄存器,保持4字节对齐
    	.data : {//所有文件的.data*放到.data段
    		*(.data*)
    	}
    
    	. = ALIGN(4);//修改当前定位寄存器,保持4字节对齐
    
    	. = .;//???
    
    	. = ALIGN(4);//修改当前定位寄存器,保持4字节对齐
    	.u_boot_list : {//所有文件的.u_boot_list*放到.u_boot_list段,且先通过SORT对
    //所有.u_boot_list*排序然后通过KEEP告诉连接器,这个段很重要,不要优化掉了哈。
    //.data段结束后,紧接着存放u-boot自有的一些function,例如u-boot command等
    		KEEP(*(SORT(.u_boot_list*)));
    	}
    
    	. = ALIGN(4);//修改当前定位寄存器,保持4字节对齐
    
    	.image_copy_end ://同__image_copy_start,参考arch/arm/lib/sections.c和
    //arch/arm/lib/relocate.S,里面有注解。
    //至此,u-boot需要自拷贝的内容结束,总结一下,包括代码段,数据段,以及u_boot_list
    	{
    		*(.__image_copy_end)
    	}
    
    	.rel_dyn_start ://用于用于动态连接的重定位信息的start,参考arch/arm/lib/sections.c ,里面有注解。
    //在老的uboot中,如果我们想要uboot启动后把自己拷贝到内存中的某个地方,只要把要拷贝的地址写给TEXT_BASE即可,
    //然后boot启动后就会把自己拷贝到TEXT_BASE内的地址处运行,在拷贝之前的代码都是相对的,不能出现绝对的跳转,否则会跑飞。
    //在新版的uboot里(2013.07),TEXT_BASE的含义改变了。它表示用户要把这段代码加载到哪里,通常是通过串口等工具。
    //然后搬移的时候由uboot自己计算一个地址来进行搬移。
    //新版的uboot采用了动态链接技术,在lds文件中有__rel_dyn_start和__rel_dyn_end,这两个符号之间
    //的区域存放着动态链接符号,只要给这里面的符号加上一定的偏移,拷贝到内存中代码的后面相应的
    //位置处,就可以在绝对跳转中找到正确的函数。*/
    
    	{
    		*(.__rel_dyn_start)
    	}
    
    	.rel.dyn : {//动态链接符存放在的段
    		*(.rel*)
    	}
    
    	.rel_dyn_end ://动态链接符段结束,参考arch/arm/lib/sections.c ,里面有注解
    	{
    		*(.__rel_dyn_end)
    	}
    
    	_end = .;//设置_end的地址为当前定位器,board_f.c里会使用它来计算
    
    	/*
    	 * Deprecated: this MMU section is used by pxa at present but
    	 * should not be used by new boards/CPUs.
    	 */
    	. = ALIGN(4096);
    	.mmutable : {
    		*(.mmutable)
    	}
    
    /*
     * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
     * __bss_base and __bss_limit are for linker only (overlay ordering)
     */
    
    	.bss_start __rel_dyn_start (OVERLAY) : {//参考arch/arm/lib/sections.c ,里面有注解
    		KEEP(*(.__bss_start));//
    		__bss_base = .;
    	}
    
    	.bss __bss_base (OVERLAY) : {//未初始化段,存放程序中未初始化的全局变量和静态变量的一块内存区域
    		*(.bss*)
    		 . = ALIGN(4);
    		 __bss_limit = .;
    	}
    
    	.bss_end __bss_limit (OVERLAY) : {//参考arch/arm/lib/sections.c ,里面有注解
    		KEEP(*(.__bss_end));
    	}
    
    	/DISCARD/ : { *(.dynsym) }
    	/DISCARD/ : { *(.dynstr*) }
    	/DISCARD/ : { *(.dynamic*) }
    	/DISCARD/ : { *(.plt*) }
    	/DISCARD/ : { *(.interp*) }
    	/DISCARD/ : { *(.gnu*) }
    	/DISCARD/ : { *(.ARM.exidx*) }
    	/DISCARD/ : { *(.gnu.linkonce.armexidx.*) }
    }
    
    

    在config.mk中:

    ifneq ($(CONFIG_SYS_TEXT_BASE),)                                                
    LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE)                                
    endif       
    

    在生成elf可执行文件u-boot的命令中就指定了链接标志LDFLAGS

    ifeq ($(CONFIG_SANDBOX),y)                                                      
    GEN_UBOOT =                                                                    
            cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds                       
                -Wl,--start-group $(__LIBS) -Wl,--end-group                        
                $(PLATFORM_LIBS) -Wl,-Map -Wl,u-boot.map -o u-boot                  
    else                                                                            
    GEN_UBOOT =                                                                    
            cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F))                       
                $(__OBJS)                                                          
                --start-group $(__LIBS) --end-group $(PLATFORM_LIBS)               
                -Map u-boot.map -o u-boot                                           
    endif  
    

    这说明只需要定义CONFIG_SYS_TEXT_BASE,编译的时候就会去设置text段的base地址。至于在哪里设置,相信大家可以猜到了,当然是板级相关的头文件啦,并且在执行第二步配置的时候会被处理,放到config.mk里去。另外需要说明一下,$(@F)表示"$@"的文件部分,如果"$@"值是"dir/foo.o",那么"$(@F)"就是"foo.o","$(@F)"相当于函数"$(notdir $@)",对应到这里,
    $(LDFLAGS_$(@F))就是LDFLAGS_u-boot啦,因为我们的目标为$(obj)u-boot

    另外,关于OVERLAY。每一个输出节可以有一个类型。类型是一个放在括号中的关键字,已定义的类型如下所示:
    NOLOAD' 这个节应当被标式讵不可载入,所以当程序运行时,它不会被载入到内存中。 DSECT'
    COPY' INFO'
    `OVERLAY'
    支持这些类型名只是为了向下兼容,它们很少使用。它们都具有相同的效果:这个节应当被标式讵不可分配,所以当程序运行时,没有内存为这个节分配。

    补充1:

    标准应用程序包括 3 类标准段空间:.text 运行代段;.data 全局变量等具有初始值的数据空间;.bss暂态变量,堆栈等数据空间;

    补充2:

    .rodata,.u_boot_list.image_copy_end 等段空间由程序员设计需要而自行定义的段空间;

    总的来说,uboot的链接脚本还是很简单的。

    总结

      构建u-boot.bin,会先在tools [examples/standalone、examples/api] arch/arm/cpu/armv7/目录下构建_depend目标,然后去tools下构建all目标,再然后构建arch/arm/cpu/armv7/start.o,然后执行LIBS构建(LIBS由lib/ fs/ drivers/ common/ api/ post/ test/ arch/arm/cpu/armv7/ arch/arm/cpu/armv7/zynq/ arch/arm/lib/ disk/ net/下的部分文件构成),然后构建board/xilinx/zynq/Makefile下的默认目标,以及$(obj)u-boot.lds,最后基于以上构建的来构建u-boot以及u-boot.bin。当然,不同的板子,构建过程多少会有些差异,不过大体思想是一样的。本文如果有错误的地方,欢迎大家指出!

    完!
    2016年7月

  • 相关阅读:
    Django视图之ORM数据库查询操作API
    Django视图之ORM更改数据库连接——配置MySQL库
    TLPI读书笔记第2章-基本概念2
    TLPI读书笔记第2章-基本概念1
    linux防火墙常用命令
    linux配置yum软件仓库
    linux进程管理
    linux文件权限
    linux用yum安装软件
    linux磁盘划分
  • 原文地址:https://www.cnblogs.com/rongpmcu/p/7662794.html
Copyright © 2011-2022 走看看