firmware由kernel和rootfs兩個部分組成,要對兩個部分先分別處理,然後再合併成一個.bin文件。先看一下這個流程。
"target/linux/ramips/image/Makefile" 文件中的最後一句:$(eval $(call BuildImage)),將BuildImage展開在這裏。BuildImage定義在 include/image.mk 文件中,其中定義了數個目標的規則。
define BuildImage
compile: compile-targets FORCE
**$(call Build/Compile)**
install: compile install-targets FORCE ...
$(call Image/BuildKernel) ## 處理vmlinux(例如用lzma工具壓縮vmlinux爲vmlinux.bin.lzma,mkimage工具將
## vmlinux.bin.lzma生成uImage.lzma)...
$(call Image/mkfs/squashfs) ## 1)用mksquashfs4工具將TARGET_DIR目錄變量製作爲root.squashfs文件系統,
## 2)用patch-deb工具將vmlinux-mt7628(由vmlinux複製的)與dtc工具生成的dtb合併,
並用lzma壓縮爲vmlinux-mt7628.bin.lzma
## 3)用mkimage工具將vmlinux-mt7628.bin.lzma生成vmlinux-mt7628.uImage
## 4)用cat命令將vmlinux-mt7628.uImage與root.squashfs合併最終的openwrt-ramips-
mt7628-mt7628-squashfs-sysupgrade.bin
## 5)用padjffs2工具給4)生成的bin加pad和jffs2 fs結束標記
## 6)判斷5)得到的bin大小是否大於ralink_default_fw_size_8M變量設置的值,如果大於,
打印警告,如果小於,將bin複製到bin/目錄下
...
endef
處理vmlinux: Image/BuildKernel
target/linux/ramips/image/Makefile:
define Image/BuildKernel
cp $(KDIR)/vmlinux.elf $(BIN_DIR)/$(VMLINUX).elf
cp $(KDIR)/vmlinux $(BIN_DIR)/$(VMLINUX).bin $(call CompressLzma,$(KDIR)/vmlinux,$(KDIR)/vmlinux.bin.lzma) $(call MkImage,lzma,$(KDIR)/vmlinux.bin.lzma,$(KDIR)/uImage.lzma)
cp $(KDIR)/uImage.lzma $(BIN_DIR)/$(UIMAGE).bin
ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),)
cp $(KDIR)/vmlinux-initramfs.elf $(BIN_DIR)/$(VMLINUX)-initramfs.elf
cp $(KDIR)/vmlinux-initramfs $(BIN_DIR)/$(VMLINUX)-initramfs.bin $(call CompressLzma,$(KDIR)/vmlinux-initramfs,$(KDIR)/vmlinux-initramfs.bin.lzma) $(call MkImage,lzma,$(KDIR)/vmlinux-initramfs.bin.lzma,$(KDIR)/uImage-initramfs.lzma)
cp $(KDIR)/uImage-initramfs.lzma $(BIN_DIR)/$(UIMAGE)-initramfs.bin
endif $(call Image/Build/Initramfs) endef
lzma壓縮內核
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/ 目錄中:
lzma e vmlinux -lc1 -lp2 -pb2 vmlinux.bin.lzma
MkImage
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/ 目錄中:
mkimage -A mips -O linux -T kernel -C lzma -a 0x80000000 -e 0x80000000 -n "MIPS OpenWrt Linux-3.14.18" -d vmlinux.bin.lzma uImage.lzma
copy
VMLINUX:=$(IMG_PREFIX)-vmlinux --> openwrt-ramips-mt7620a-vmlinux UIMAGE:=$(IMG_PREFIX)-uImage --> openwrt-ramips-mt7620a-uImage
cp $(KDIR)/uImage.lzma $(BIN_DIR)/$(UIMAGE).bin
把uImage.lzma複製到bin/ramips/目錄下:
cp $(KDIR)/uImage.lzma bin/ramips/openwrt-ramips-mt7620a-uImage
製作squashfs,生成.bin: $(call Image/mkfs/squashfs)
define Image/mkfs/squashfs
@mkdir -p $(TARGET_DIR)/overlay
$(STAGING_DIR_HOST)/bin/mksquashfs4 $(TARGET_DIR) $(KDIR)/root.squashfs -nopad -noappend -root-owned -comp $(SQUASHFSCOMP) $(SQUASHFSOPT) -processors $(if $(CONFIG_PKG_BUILD_JOBS),$(CONFIG_PKG_BUILD_JOBS),1)
$(call Image/Build,squashfs)
endif
mkdir -p $(TARGET_DIR)/overlay
mkdir -p build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/root-ramips/overlay
mksquashfs4
$(STAGING_DIR_HOST)/bin/mksquashfs4 $(TARGET_DIR) $(KDIR)/root.squashfs -nopad -noappend -root-owned -comp $(SQUASHFSCOMP) $(SQUASHFSOPT) -processors $(if $(CONFIG_PKG_BUILD_JOBS),$(CONFIG_PKG_BUILD_JOBS),1)
製作squashfs文件系統,生成root.squashfs:
mksquashfs4 root-ramips root.squashfs -nopad -noappend -root-owned -comp gzip -b 256k -p '/dev d 755 0 0' -p '/dev/console c 600 0 0 5 1' -processors 1
$(call Image/Build,squashfs)
在 target/linux/ramips/image/Makefile 中:
define Image/Build
$(call Image/Build/$(1))
dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=128k conv=sync
$(call Image/Build/Profile/$(PROFILE),$(1))
endef
- dd if=(KDIR)/root.squashfsof=(BIN_DIR)/$(IMG_PREFIX)-root.squashfs bs=128k conv=sync
dd if=build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/root.squashfs of=bin/ramips/openwrt-ramips-mt7620-root.squashfs bs=128k conv=sync
- (callImage/Build/Profile/(PROFILE),squashfs)
target/linux/ramips/mt7620a/profiles/00-default.mk, 中調用 Profile 函數:$(eval $(call Profile,Default))
include/target.mk 中定義了 Profile 函數, 其中令 PROFILE=Default
define Image/Build/Profile/Default
$(call Image/Build/Profile/MT7620a,$(1)) ...
endef
規則依賴序列如下:
$(call Image/Build/Profile/$(PROFILE),squashfs)
--> $(call BuildFirmware/Default8M/squashfs,squashfs,mt7620a,MT7620a) --> $(call BuildFirmware/OF,squashfs,mt7620a,MT7620a,8060928) --> $(call MkImageLzmaDtb,mt7620a,MT7620a) --> $(call PatchKernelLzmaDtb,mt7620a,MT7620a) --> $(call MkImage,lzma,$(KDIR)/vmlinux-mt7620a.bin.lzma,$(KDIR)/vmlinux-mt7620a.uImage) --> $(call MkImageSysupgrade/squashfs,squashfs,mt7620a,8060928)
其中的主要步驟:
- 複製: cp (KDIR)/vmlinux(KDIR)/vmlinux-mt7620a
- 生成dtb文件: (LINUXDIR)/scripts/dtc/dtc?Odtb?o(KDIR)/MT7620a.dtb ../dts/MT7620a.dts
- 將內核與dtb文件合併:(STAGINGDIRHOST)/bin/patch?dtb(KDIR)/vmlinux-mt7620a $(KDIR)/MT7620a.dtb
- 使用lzma壓縮:(callCompressLzma,(KDIR)/vmlinux-mt7620a,$(KDIR)/vmlinux-mt7620a.bin.lzma)
- 將lzma壓縮後的文件經過mkimage工具處理,即在頭部添加uboot可識別的信息。
接下來就是合併生成firmware固件了:
MkImageSysupgrade/squashfs, squashfs, mt7620a,8060928
cat vmlinux-mt7620a.uImage root.squashfs > openwrt-ramips-mt7620-mt7620a-squashfs-sysupgrade.bin
--> 製作squashfs bin文檔, 並確認它的大小 < 8060928 纔是有效的,否則報錯