天天看點

ASUS N14U 源碼編譯過程分析(上)image目标

主要涉及到兩個關鍵的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進行描述。

繼續閱讀