主要涉及到兩個關鍵的Makfile,因為這些Makefile的自動化程度不高,是以代碼顯得很繁瑣,但正因為如此,才相對顯得比較簡單。
首先是asuswrt/release/src-ra-mt7620目錄下的Makefile
略去前面的變量定義部分,進入關鍵的部分:
image目标
image:
@if [ -z "$(BUILD_NAME)" ]; then \
echo "No BUILD_NAME is assigned"; \
exit 1; \
fi
@rm -f image/$(BUILD_NAME)_$(KERNEL_VER).$(FS_VER)_$(SERIALNO).trx
@$(MAKE) -C router image
ifeq ($(CONFIG_RALINK),y)
#開始生成image
else
#非ralink裝置,隻進行簡單的打包
endif
生成image部分沒有什麼特别的編譯行為,但是裡面對檔案進行相關的打包操作,很有技巧性,值得學習和研究。
核心打包
@rm -rf $(PLATFORMDIR)/zImage.lzma ; \
mipsel-linux-objcopy -O binary $(LINUXDIR)/vmlinux $(PLATFORMDIR)/vmlinus ; \
asustools/lzma -9 -f -c $(PLATFORMDIR)/vmlinus > $(PLATFORMDIR)/zImage.lzma ; \
cp -f $(PLATFORMDIR)/zImage.lzma $(PLATFORMDIR)/zImage.img ; \
首先生成kernel的bin目标檔案vmlinus,然後調用lzma進行最高強度的壓縮,生成zImage.lzma,最後将檔案拷貝到$(PLATFORMDIR)目錄,
通過前面的定義
export PLATFORM := mipsel-uclibc
export PLATFORMDIR := $(SRCBASE)/router/$(PLATFORM)
可知,該目錄位于router/mipsel-uclibc
對核心進行位元組填充
此部分的代碼比較多,但是容易了解,用到了shell中的wc、awk、expr、dd、tr等指令,此處不詳述,感興趣的讀者可以對照Makefile檔案研究。
生成最終的刷機固件
核心代碼是調用mkimage指令,生成trx刷機固件檔案。
我們知道mkimage需要知道代碼的入口點,這個入口點如何用程式擷取呢?這個技巧值得我們去學習:
@ENTRY=` grep "Entry" | awk '{print $$4}'` ; \
ISIZE=`wc -c $(PLATFORMDIR)/zImage.img | awk '{print $$1}'` ; \
KSIZE=`wc -c $(PLATFORMDIR)/zImage.lzma | awk '{print $$1}'` ; \
RSIZE=`wc -c $(PLATFORMDIR)/target.image | awk '{print $$1}'` ; \
PAD2=`expr $${ISIZE} - $${KSIZE} - $${RSIZE}` ; \
RFSOFFSET=`expr 64 + $${KSIZE} + $${PAD2}` ; \
echo "PAD2: $${PAD2}" ; \
asustools/mkimage -A mips -O linux -T kernel -C lzma -a 80000000 -e $${ENTRY} -r $${RFSOFFSET} \
-n $(BUILD_NAME) -V "$(KERNEL_VER)" "$(FS_VER)" "0" "0" "0" "0" "0" "0" "0" "0" \
-d $(PLATFORMDIR)/zImage.img image/$(BUILD_NAME)_$(KERNEL_VER).$(FS_VER)_$(SERIALNO)_$(SWPJVER)$(EXTENDNO).trx ; \
它利用readelf -h,讀出vmlinux的header部分資訊:
ABI Version: 0
Type: EXEC (Executable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x8000c150
Start of program headers: 52 (bytes into file)
Start of section headers: 3445604 (bytes into file)
Flags: 0x70001001, noreorder, o32, mips32r2
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 21
Section header string table index: 18
利用grep "Entry" | awk '{print $$4}',就能擷取到入口位址0x8000c150
通配符目标
利用通配符,實作了一些簡化的操作,如:
mk-%:
@$(MAKE) -C router $(shell echo $@ | sed s/mk-//)
和:
%: dummy
@[ ! -d router/$* ] || $(MAKE) -C router $@
%-clean: dummy
@-[ ! -d router/$* ] || $(MAKE) -C router $@
%-install: dummy
@[ ! -d router/$* ] || $(MAKE) -C router $* $@
%-stage: dummy
@[ ! -d router/$* ] || $(MAKE) -C router $* $@
%-build: dummy
$(MAKE) $*-clean $*
%-tags: dummy
@[ ! -d router/$* ] || ctags -a -R $(CTAGS_EXCLUDE_OPT) $(SRCBASE)/../src/router/$*
all目标
有意放在最後來介紹,因為此處就要跳轉到router目錄,進行下一個重要編譯過程
all: rt_ver
@echo ""
@echo "Building $(BUILD_NAME)_$(KERNEL_VER).$(FS_VER)_$(SERIALNO).trx"
@echo ""
@echo ""
@-mkdir image
@$(MAKE) -C router all
@$(MAKE) -C router install
@$(MAKE) image
實際上是進入到router目錄,對all和install目标進行編譯。
我将在下一篇文章中,對router目錄中的Makefile進行描述。