一般按tomato编译教程,输入类似make r2m的指令之后,就会一路编译下去,生成最终固件。本文对其主Makefile的执行流程进行介绍。

(1)make r2m之后,首先的目标是r2m

r2m:
    @$(MAKE) m MIPS32=r2

(2)很明显,转到m目标

m:
ifeq ($(CONFIG_LINUX26),y)
    @$(MAKE) bin OPENVPN=y BBEXTRAS=y EBTABLES=y NO_LIBOPT=y IPV6SUPP=y B=E BUILD_DESC="Max" USB="" NOCAT=y NFS=y SNMP=y DNSCRYPT=y PPTPD=y TOR=y IPSEC=y
endif

(3)bin目标。这个目标定义了很多编译选项,生成了几个关键的config文件

bin:
ifeq ($(B),)
    @echo $@" is not a valid target!"
    @false
endif
    @cp router/config_base router/config_$(lowercase_B)
    @cp router/busybox/config_base router/busybox/config_$(lowercase_B)
    @cp $(LINUXDIR)/config_base $(LINUXDIR)/config_$(lowercase_B)

    $(call RouterOptions, router/config_$(lowercase_B))
    $(call KernelConfig, $(LINUXDIR)/config_$(lowercase_B))
    $(call BusyboxOptions, router/busybox/config_$(lowercase_B))

    @$(MAKE) setprofile N=$(TPROFILE) B=$(B) DESC="$(BUILD_DESC)" USB="$(USB)"

    @$(MAKE) all

(4)转到bin目标中的setprofile目标。这个目标首先生成了tomato_profile.h和tomato_profile.mak文件。然后就是将bin目标中生成的各种config文件设置为make目标默认的.config文件。

setprofile:
    echo '#ifndef TOMATO_PROFILE' > router/shared/tomato_profile.h
    echo '#define TOMATO_$(N) 1' >> router/shared/tomato_profile.h
    echo '#define PROFILE_G 1' >> router/shared/tomato_profile.h
    echo '#define PROFILE_N 2' >> router/shared/tomato_profile.h
    echo '#define TOMATO_PROFILE PROFILE_$(N)' >> router/shared/tomato_profile.h
    echo '#define TOMATO_PROFILE_NAME "$(N)"' >> router/shared/tomato_profile.h
    echo '#define TOMATO_BUILD_NAME "$(B)"' >> router/shared/tomato_profile.h
    echo '#define TOMATO_BUILD_DESC "$(DESC)$(EXTRA_64KDESC)"' >> router/shared/tomato_profile.h
    echo '#ifndef CONFIG_NVRAM_SIZE' >> router/shared/tomato_profile.h
    echo '#define CONFIG_NVRAM_SIZE $(NVRAM_SIZE)' >> router/shared/tomato_profile.h
    echo '#endif' >> router/shared/tomato_profile.h
    echo '#endif' >> router/shared/tomato_profile.h

    echo 'TOMATO_$(N) = 1' > tomato_profile.mak
    echo 'PROFILE_G = 1' >> tomato_profile.mak
    echo 'PROFILE_N = 2' >> tomato_profile.mak
    echo 'TOMATO_PROFILE = $$(PROFILE_$(N))' >> tomato_profile.mak
    echo 'TOMATO_PROFILE_NAME = "$(N)"' >> tomato_profile.mak
    echo 'TOMATO_BUILD = "$(B)"' >> tomato_profile.mak
    echo 'TOMATO_BUILD_NAME = "$(B)"' >> tomato_profile.mak
    echo 'TOMATO_BUILD_DESC = "$(DESC)$(EXTRA_64KDESC)"' >> tomato_profile.mak
    echo 'TOMATO_PROFILE_L = $(lowercase_N)' >> tomato_profile.mak
    echo 'TOMATO_PROFILE_U = $(uppercase_N)' >> tomato_profile.mak
    echo 'TOMATO_BUILD_USB = "$(USB)"' >> tomato_profile.mak

    echo 'export EXTRACFLAGS := $(EXTRA_CFLAGS) -DBCMWPA2 -funit-at-a-time -Wno-pointer-sign -mtune=mips32 -mips32 $(if $(filter $(NVRAM_SIZE),0),,-DCONFIG_NVRAM_SIZE=$(NVRAM_SIZE)) $(EXTRA_64KCFLAG)' >> tomato_profile.mak

# Note that changes to variables in tomato_profile.mak don't
# get propogated to this invocation of make!
    @echo ""
    @echo "Using $(N) profile, $(B) build config."
    @echo ""

    @cd $(LINUXDIR) ; \
        rm -f config_current ; \
        ln -s config_$(lowercase_B) config_current ; \
        cp -f config_current .config

    @cd router/busybox && \
        rm -f config_current ; \
        ln -s config_$(lowercase_B) config_current ; \
        cp config_current .config

    @cd router ; \
        rm -f config_current ; \
        ln -s config_$(lowercase_B) config_current ; \
        cp config_current .config

    @$(MAKE) -C router oldconfig

 

(5)setprofile目标最后一句看到进入router目录执行oldconfig目标

oldconfig oldconf: koldconf roldconf dependconf bboldconf

oldconfig依赖4个目标koldconf roldconf dependconf bboldconf。koldconf目标对应linux内核,bboldconf对应busybox,另外2个目标是router目录自身的。

可以一次跟踪下去。

(6)setprofile目标执行完了,linux内核和busybox编译就完成了。再回到bin目标的最后一句,到了all目标。

tomato_ver:
    @echo ""
    @btools/uversion.pl --gen $(V1) $(mips_rev)$(beta)$(V2) $(ND) $(current_BUILD_USB) $(current_BUILD_DESC)

ifeq ($(TOMATO_BUILD),)

all:
    $(MAKE) a

else

all: tomato_ver

。。。。。。。。。。。。。。。。

 

all目标很长,一路跟踪下去,先是定义了版本号相关变量,然后进入-C router all,-C router install,-C btools。接着删除了旧的固件,最后是依据make传输的版本参数生成新的固件。

新固件使用btools目录下的fpkg打包工具完成,类似下面:

    # Create generic TRX image
    @btools/fpkg -i lzma-loader/loader.gz -i $(LINUXDIR)/arch/mips/brcm-boards/bcm947xx/compressed/vmlinuz -a 1024 -i router/mipsel-uclibc/target.image \
        -t image/tomato-$(ND)$(current_BUILD_USB)$(if $(filter $(NVRAM_SIZE),0),,-NVRAM$(NVRAM_SIZE)K)-$(current_TOMATO_VER).$(V1)$(mips_rev)$(beta)$(V2)-$(current_BUILD_DESC).trx \
        | tee -a fpkg.log

fpkg工具其实就是按照一定的参数把 loader.gz,vmlinuz和target.image连接起来,生成新的固件。loader.gz是lzma解压缩工具,vmlinuz就是内核,target.image是除内核之外的其它部分。想研究tomato固件解包的,可以仔细研究下fpkg工具和lzma压缩算法^_^。

固件出来了,主要流程分析完成了。至于vmlinuz和target.image是如何生成的,这个就得研究对应部分的makefile流程了。

 

 

posted on 2014-04-23 19:24  网速优化路由器  阅读(1024)  评论(0编辑  收藏  举报