openwrt源码框架解析

转载自https://blog.csdn.net/clirus/article/details/50496958

本篇的主要目的是想通过分析Makefile,了解openwrt编译过程。着重关注以下几点:

  1. openwrt目录结构
  2. 主Makefile的解析过程,各子目录的目标生成。
  3. kernel编译过程
  4. firmware的生成过程
  5. 软件包的编译过程

openwrt目录结构

官方源下载速度太度,我从github上clone了openwrt的代码仓库。

git clone https://github.com/openwrt-mirror/openwrt.git

openwrt目录结构

上图是openwrt目录结构,其中第一行是原始目录,第二行是编译过程中生成的目录。各目录的作用是:

  • tools - 编译时需要一些工具, tools里包含了获取和编译这些工具的命令。里面是一些Makefile,有的可能还有patch。每个Makefile里都有一句  ( e v a l (call HostBuild)),表示编译这个工具是为了在主机上使用的。
  • toolchain - 包含一些命令去获取kernel headers, C library, bin-utils, compiler, debugger
  • target - 各平台在这个目录里定义了firmware和kernel的编译过程。
  • package - 包含针对各个软件包的Makefile。openwrt定义了一套Makefile模板,各软件参照这个模板定义了自己的信息,如软件包的版本、下载地址、编译方式、安装地址等。
  • include - openwrt的Makefile都存放在这里。
  • scripts - 一些perl脚本,用于软件包管理。

  • dl - 软件包下载后都放到这个目录里
  • build_dir - 软件包都解压到build_dir/里,然后在此编译
  • staging_dir - 最终安装目录。tools, toolchain被安装到这里,rootfs也会放到这里。
  • feeds - OpenWrt环境所需要的软件包套件
  • bin - 编译完成之后,firmware和各ipk会放到此目录下。

feeds说明:

最重要的feeds有:

‘packages’一些额外的基础路由器特性软件

‘LuCI’OpenWrt默认的GUI

‘Xwrt’另一种可选的GUI界面

需要能够连接互联网。

在下载之前可以通过查看’feeds.conf.default’文件,来检查哪些文件需要包含在环境中。

开始下载,使用:

[openwrt@localhost trunk]$ ./scripts/feeds update -a

安装feeds包,只有安装之后,在后面的make menuconfig时,才可以对相关配置进行勾选。

[openwrt@localhost trunk]$ ./scripts/feeds install -a

如果更新了feeds的配置文件,需要添加新的软件包用于生成系统。只需进行重复操作:

[openwrt@localhost trunk]$ ./scripts/feeds update -a

[openwrt@localhost trunk]$ ./scripts/feeds install -a


可使用的feeds列表配置在feeds.conf目录下或者feeds.conf.default。这个文件包含了feeds列表,每一行又三部分组成,feed方法,feed 名字和feed源

下面是一个feeds.conf.default的例子:

src-git packages https://github.com/openwrt/packages.git 
src-git luci http://git.openwrt.org/project/luci.git
src-git routing https://github.com/openwrt-routing/packages.git
src-git telephony http://git.openwrt.org/feed/telephony.git
src-git management https://github.com/openwrt-management/packages.git
src-git oldpackages http://git.openwrt.org/packages.git

#src-svn xwrt http://x-wrt.googlecode.com/svn/trunk/package #src-svn phone svn://svn.openwrt.org/openwrt/feeds/phone #src-svn efl svn://svn.openwrt.org/openwrt/feeds/efl #src-svn xorg svn://svn.openwrt.org/openwrt/feeds/xorg #src-svn desktop svn://svn.openwrt.org/openwrt/feeds/desktop #src-svn xfce svn://svn.openwrt.org/openwrt/feeds/xfce #src-svn lxde svn://svn.openwrt.org/openwrt/feeds/lxde #src-link custom /usr/src/openwrt/custom-feed

下面是feed支持的方法类型:

src-bzr    通过使用bzr从数据源的path/URL下载数据

src-cpy   通过从数据源path拷贝数据

src-darcs  通过使用darcs从数据源path/URL下载数据

src-git     通过使用git从数据源path/URL下载数据

src-hg     通过使用hg从数据源path/URL 下载数据

src-link   创建一个数据源path的symlink

src-svn    通过使用svn从数据源path/URL下载数据


OpenWrt Development Guide

main Makefile

openwrt根目录下的Makefile是执行make命令时的入口。从这里开始分析。

world:

ifndef ($(OPENWRT_BUILD),1) # 第一个逻辑 ... else # 第二个逻辑 ... endif

上面这段是主Makefile的结构,可以得知:

  1. 执行make时,若无任何目标指定,则默认目标是world
  2. 执行make时,无参数指定,则会进入第一个逻辑。如果执行命令make OPENWRT_BUILD=1,则直接进入第二个逻辑。

编译时一般直接使用make V=s -j5这样的命令,不会指定OPENWRT_BUILD变量

第一个逻辑

 override OPENWRT_BUILD=1 export OPENWRT_BUILD

更改了OPENWRT_BUILD变量的值。这里起到的作用是下次执行make时,会进入到第二逻辑中。

toplevel.mk中的 %:: 解释world目标的规则。

prereq:: prepare-tmpinfo .config @+$(</span>MAKE) -r -s tmp/.prereq-build <span class="hljs-variable">$(PREP_MK) @+$(</span>NO_TRACE_MAKE) -r -s <span class="hljs-variable">$@ %:: @+$(</span>PREP_MK) <span class="hljs-variable">$(NO_TRACE_MAKE) -r -s prereq @( \
        cp .config tmp/.config; \
        ./scripts/config/conf --defconfig=tmp/.config -w tmp/.config Config.in > /dev/null 2>&1; \ if ./scripts/kconfig.pl '>' .config tmp/.config | grep -q CONFIG; then \
            printf "$(_R)WARNING: your configuration is out of sync. Please run make menuconfig, oldconfig or defconfig!$(_N)\n" >&2; \
        fi \
    ) @+$(</span>ULIMIT_FIX) <span class="hljs-variable">$(SUBMAKE) -r $@

执行 make V=s 时,上面这段规则简化为:

prereq:: prepare-tmpinfo .config @make -r -s tmp/.prereq-build @make V=ss -r -s prereq %:: @make V=s -r -s prereq @make -w -r world

可见其中最终又执行了prereq和world目标,这两个目标都会进入到第二逻辑中。

第二逻辑

首先就引入了target, package, tools, toolchain这四个关键目录里的Makefile文件

 include target/Makefile include package/Makefile include tools/Makefile include toolchain/Makefile

这些子目录里的Makefile使用include/subdir.mk里定义的两个函数来动态生成规则,这两个函数是subdir和stampfile

stampfile

拿target/Makefile举例:

(eval(call stampfile,$(curdir),target,prereq,.config))

会生成规则:

 target/stamp-prereq:=$(</span>STAGING_DIR)/stamp/.target_prereq <span class="hljs-variable">$$</span>(target/stamp-prereq): <span class="hljs-variable">$(TMP_DIR)/.build .config @+$(SCRIPT_DIR)/timestamp.pl -n $$(target/stamp-prereq) target .config || \
        make $$</span>(target/flags-prereq) target/prereq <span class="hljs-variable">@mkdir</span> -p <span class="hljs-variable">$$$$</span>(<span class="hljs-keyword" style="color:rgb(0,0,255);">dirname</span> <span class="hljs-variable">$$(target/stamp-prereq)) @touch $$</span>(target/stamp-prereq) <span class="hljs-variable">$$(if $(call debug,target,v),,.SILENT: $$(target/stamp-prereq))

  .PRECIOUS: $$(target/stamp-prereq) # work around a make bug

  target//clean:=target/stamp-prereq/clean target/stamp-prereq/clean: FORCE @rm -f $$</span>(target/stamp-prereq) </pre>
<p style="font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;">
所以可以简单的看作:&nbsp;<span class="MathJax_Preview" style="color:rgb(136,136,136);"></span>(eval(call stampfile,<span class="MathJax_Preview" style="color:rgb(136,136,136);"></span>(curdir),target,prereq,.config))生成了目标(target/stamp-prereq)</p>
<ul style="font-size:12px;list-style:none;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;"><li style="list-style: !important;">
对于target分别生成了:<span class="MathJax_Preview" style="color:rgb(136,136,136);"></span>(target/stamp?preq),(target/stamp-copile), $(target/stamp-install)<br></li><li style="list-style: !important;">
toolchain : $(toolchain/stamp-install)<br></li><li style="list-style: !important;">
package :&nbsp;<span class="MathJax_Preview" style="color:rgb(136,136,136);"></span>(package/stamp?preq),(package/stamp-cleanup),&nbsp;<span class="MathJax_Preview" style="color:rgb(136,136,136);"></span>(package/stamp?compile),(package/stamp-install)<br></li><li style="list-style: !important;">
tools : $(tools/stamp-install)</li></ul><p style="font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;">
<a href="http://www.right.com.cn/forum/thread-73443-1-3.html" rel="nofollow" style="text-decoration:none;color:rgb(0,0,0);" target="_blank">OpenWrt的主Makefile工作过程</a></p>
<h4 id="subdir" style="font-size:14px;color:rgb(51,51,51);font-family:Verdana, Arial, Helvetica, sans-serif;">
subdir</h4>
<p style="font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;">
subdir这个函数写了一大堆东西,看起来很复杂 。</p>
<p style="font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;">
$(call subdir, target) 会遍历下的子目录,执行 make -C 操作。这样就切入子目录中去了。</p>
<h3 style="font-size:16px;font-family:Verdana, Arial, Helvetica, sans-serif;"><a name="t4"></a>
目录变量</h3>
<p style="font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;">
几个重要的目录路径:</p>
<ul style="font-size:12px;list-style:none;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;"><li style="list-style: !important;">
<p>
KERNEL_BUILD_DIR</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.14.18</p>
</blockquote>
</li><li style="list-style: !important;">
<p>
LINUX_DIR</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.14.18</p>
</blockquote>
</li><li style="list-style: !important;">
<p>
KDIR</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a</p>
</blockquote>
</li><li style="list-style: !important;">
<p>
BIN_DIR</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
bin/ramips<br>
Makefile中包含了rules.mk, target.mk等.mk文件,这些文件中定义了许多变量,有些是路径相关的,有些是软件相关的。这些变量在整个Makefile工程中经常被用到,</p>
</blockquote>
</li><li style="list-style: !important;">
<p>
TARGET_ROOTFS_DIR</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2</p>
</blockquote>
</li><li style="list-style: !important;">
<p>
BUILD_DIR</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2</p>
</blockquote>
</li><li style="list-style: !important;">
<p>
STAGING_DIR_HOST</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2</p>
</blockquote>
</li><li style="list-style: !important;">
<p>
TARGET_DIR</p>
<blockquote style="border:2px solid rgb(239,239,239);color:rgb(51,51,51);min-height:35px;line-height:1.6em;">
<p>
build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/root-ramips</p>
</blockquote>
</li></ul><h2 id="kernel-" style="font-size:21px;font-family:Verdana, Arial, Helvetica, sans-serif;"><a name="t5"></a>
kernel 编译:</h2>
<p style="font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;">
target/linux/ramips/Makefile:&nbsp;$(eval $(call BuildTarget))<br>
target/linux/Makefile :&nbsp;export TARGET_BUILD=1<br>
include/target.mk:</p>
<pre style="font-size:12px;line-height:21px;background-color:rgb(255,255,255);">ife<span class="hljs-string" style="color:rgb(163,21,21);">q (<span class="hljs-variable">$(</span>TARGET_BUILD)</span>,<span class="hljs-number">1</span>)
  include <span class="hljs-variable">$(</span>INCLUDE_DIR)/kernel-build.mk
  BuildTarget?=<span class="hljs-variable">$(</span>BuildKernel)
endif</pre>
<p style="font-size:12px;font-family:Verdana, Arial, Helvetica, sans-serif;line-height:21px;">
BuildKernel是include/kernel-build.mk定义的一个多行变量,其中描述了如何编译内核, 主要关注其中install规则的依赖链:</p>
<pre style="font-size:12px;line-height:21px;background-color:rgb(255,255,255);"> <span class="hljs-variable">$(</span>KERNEL_BUILD_DIR)/symtab.h: FORCE
	rm -f <span class="hljs-variable">$(</span>KERNEL_BUILD_DIR)/symtab.h
	touch <span class="hljs-variable">$(</span>KERNEL_BUILD_DIR)/symtab.h
	+<span class="hljs-variable">$(</span>MAKE) <span class="hljs-variable">$(</span>KERNEL_MAKEOPTS) vmlinux
	... <span class="hljs-variable">$(</span>LINUX_DIR)/.<span class="hljs-keyword" style="color:rgb(0,0,255);">image</span>: <span class="hljs-variable">$(</span>STAMP_CONFIGURED) <span class="hljs-variable">$(</span><span class="hljs-keyword" style="color:rgb(0,0,255);">if</span> <span class="hljs-variable">$(</span>CONFIG_STRIP_KERNEL_EXPORTS),<span class="hljs-variable">$(</span>KERNEL_BUILD_DIR)/symtab.h) FORCE <span class="hljs-variable">$(</span>Kernel/CompileImage) <span class="hljs-variable">$(</span>Kernel/CollectDebug)
	touch <span class="hljs-variable">$$@


  install: $(</span>LINUX_DIR)/.<span class="hljs-keyword" style="color:rgb(0,0,255);">image</span> +<span class="hljs-variable">$(MAKE) -C image compile install TARGET_BUILD= 
1. 触发make vmlinux命令生成vmlinux: install --> $(</span><span class="hljs-constant">LINUX_DIR)</span>/.image --&gt; <span class="hljs-variable">$(KERNEL_BUILD_DIR)/symtab.h --> `$(MAKE) $(KERNEL_MAKEOPTS) vmlinux` 2. 对vmlinux做objcopy, strip操作: $(</span><span class="hljs-constant">LINUX_DIR)</span>/.image --&gt; <span class="hljs-variable">$(Kernel/CompileImage) --> $(</span>call <span class="hljs-constant">Kernel/CompileImage/Default)</span> --&gt; <span class="hljs-variable">$(call Kernel/CompileImage/Default) $(</span><span class="hljs-constant">KERNEL_CROSS)</span>objcopy -<span class="hljs-constant">O </span>binary <span class="hljs-variable">$(OBJCOPY_STRIP) -S $(</span><span class="hljs-constant">LINUX_DIR)</span>/vmlinux <span class="hljs-variable">$(LINUX_KERNEL)$(1)
        --> build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/vmlinux $(</span><span class="hljs-constant">KERNEL_CROSS)</span>objcopy <span class="hljs-variable">$(OBJCOPY_STRIP) -S $(</span><span class="hljs-constant">LINUX_DIR)</span>/vmlinux <span class="hljs-variable">$(KERNEL_BUILD_DIR)/vmlinux$(1).elf
        --> build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/vmlinux.elf $(</span><span class="hljs-constant">CP)</span> <span class="hljs-variable">$(LINUX_DIR)/vmlinux $(KERNEL_BUILD_DIR)/vmlinux.debug
        --> build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/vmlinux.debug

生成firmware

firmware由kernel和rootfs两个部分组成,要对两个部分先分别处理,然后再合并成一个.bin文件。先看一下这个流程。

“target/linux/ramips/image/Makefile” 文件中的最后一句: ( e v a l (call BuildImage)),将BuildImage展开在这里。BuildImage定义在 include/image.mk 文件中,其中定义了数个目标的规则。

define BuildImage

    compile: compile-targets FORCE
        **$(call Build/Compile)**

    install: compile install-targets FORCE ... $(call Image/BuildKernel) <span class="hljs-comment" style="color:#008000;">## 处理vmlinux</span> <span class="hljs-keyword" style="color:rgb(0,0,255);">...</span> $(call Image/mkfs/squashfs) ## 生成squashfs,并与vmlinux合并成一个.bin文件 ... endef

处理vmlinux: Image/BuildKernel

target/linux/ramips/image/Makefile:

define Image/BuildKernel
    cp $(KDIR)</span>/vmlinux.elf <span class="hljs-variable">$(BIN_DIR)/$(VMLINUX).elf
    cp $(KDIR)</span>/vmlinux <span class="hljs-variable">$(BIN_DIR)/$(VMLINUX)</span>.bin <span class="hljs-variable">$(call CompressLzma,$(KDIR)</span>/vmlinux,<span class="hljs-variable">$(KDIR)/vmlinux.bin.lzma) $(call MkImage,lzma,$(KDIR)/vmlinux.bin.lzma,$(KDIR)/uImage.lzma)
    cp $(KDIR)</span>/uImage.lzma <span class="hljs-variable">$(BIN_DIR)/$(UIMAGE).bin
ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),)
    cp $(KDIR)</span>/vmlinux-initramfs.elf <span class="hljs-variable">$(BIN_DIR)/$(VMLINUX)-initramfs.elf
    cp $(KDIR)</span>/vmlinux-initramfs <span class="hljs-variable">$(BIN_DIR)/$(VMLINUX)</span>-initramfs.bin <span class="hljs-variable">$(call CompressLzma,$(KDIR)</span>/vmlinux-initramfs,<span class="hljs-variable">$(KDIR)/vmlinux-initramfs.bin.lzma) $(call MkImage,lzma,$(KDIR)/vmlinux-initramfs.bin.lzma,$(KDIR)/uImage-initramfs.lzma)
    cp $(KDIR)</span>/uImage-initramfs.lzma <span class="hljs-variable">$(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:=$(</span><span class="hljs-constant">IMG_PREFIX)</span>-vmlinux --&gt; openwrt-ramips-mt7620a-vmlinux <span class="hljs-constant">UIMAGE:</span>=<span class="hljs-variable">$(IMG_PREFIX)-uImage --> openwrt-ramips-mt7620a-uImage
cp $(</span><span class="hljs-constant">KDIR)</span>/uImage.lzma <span class="hljs-variable">$(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 $(</span><span class="hljs-constant">TARGET_DIR</span>)/overlay <span class="hljs-variable">$(STAGING_DIR_HOST)/bin/mksquashfs4 $(</span><span class="hljs-constant">TARGET_DIR</span>) <span class="hljs-variable">$(KDIR)/root.squashfs -nopad -noappend -root-owned -comp $(</span><span class="hljs-constant">SQUASHFSCOMP</span>) <span class="hljs-variable">$(SQUASHFSOPT) -processors $(</span><span class="hljs-keyword" style="color:rgb(0,0,255);">if</span> <span class="hljs-variable">$(CONFIG_PKG_BUILD_JOBS),$(</span><span class="hljs-constant">CONFIG_PKG_BUILD_JOBS</span>),<span class="hljs-number">1</span>) <span class="hljs-variable">$(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

$(</span><span class="hljs-constant">STAGING_DIR_HOST</span>)/bin/mksquashfs4 <span class="hljs-variable">$(TARGET_DIR) $(</span><span class="hljs-constant">KDIR</span>)/root.squashfs -nopad -noappend -root-owned -comp <span class="hljs-variable">$(SQUASHFSCOMP) $(</span><span class="hljs-constant">SQUASHFSOPT</span>) -processors <span class="hljs-variable">$(if $(</span><span class="hljs-constant">CONFIG_PKG_BUILD_JOBS</span>),<span class="hljs-variable">$(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 $(</span>call <span class="hljs-constant">Image</span>/<span class="hljs-constant">Build</span>/<span class="hljs-variable">$(1))
    dd if=$(</span><span class="hljs-constant">KDIR</span>)/root.<span class="hljs-variable">$(1) of=$(</span><span class="hljs-constant">BIN_DIR</span>)/<span class="hljs-variable">$(IMG_PREFIX)-root.$(</span><span class="hljs-number">1</span>) bs=<span class="hljs-number">128</span>k conv=sync <span class="hljs-variable">$(call Image/Build/Profile/$(</span><span class="hljs-constant">PROFILE</span>),<span class="hljs-variable">$(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 函数: ( e v a l (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)
  --> $(</span>call <span class="hljs-constant">BuildFirmware</span>/<span class="hljs-constant">Default8M</span>/squashfs,squashfs,mt7620a,<span class="hljs-constant">MT7620a</span>)</span> </span> -<span class="ruby"><span class="hljs-input"><span class="hljs-prompt" style="color:rgb(43,145,175);">-&gt;</span> <span class="hljs-variable">$(call BuildFirmware/OF,squashfs,mt7620a,MT7620a,8060928)  --> $(</span>call <span class="hljs-constant">MkImageLzmaDtb</span>,mt7620a,<span class="hljs-constant">MT7620a</span>)</span> </span> -<span class="ruby"><span class="hljs-input"><span class="hljs-prompt" style="color:rgb(43,145,175);">-&gt;</span> <span class="hljs-variable">$(call PatchKernelLzmaDtb,mt7620a,MT7620a)  --> $(</span>call <span class="hljs-constant">MkImage</span>,lzma,<span class="hljs-variable">$(KDIR)/vmlinux-mt7620a.bin.lzma,$(</span><span class="hljs-constant">KDIR</span>)/vmlinux-mt7620a.uImage)</span> </span> -<span class="ruby"><span class="hljs-prompt" style="color:rgb(43,145,175);">-&gt;</span> <span class="hljs-variable">$(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 才是有效的,否则报错。


总结: 整个流程下来,其实最烦索的还是对内核生成文件vmlinux的操作,经过了objcopy, patch-dtb, lzma, mkimage 等过程生成一个uImage,再与mksquashfs工具制作的文件系统rootfs.squashfs合并。



        </div>

猜你喜欢

转载自blog.csdn.net/sherry_unique/article/details/82220168