Ubuntu 14.04安装openwrt

OpenWRT 编译环境搭建

配置编译环境

必须使用非root用户,ArchLinux需要创建新用户。

安装依赖包

// Ubuntu 14.04 必选
# apt-get install asciidoc bash bc binutils bzip2 fastjar flex git-core g++ build-essential util-linux gawk libgtk2.0-dev intltool jikespg zlib1g-dev genisoimage libncurses5-dev libssl-dev patch perl-modules python2.7-dev rsync ruby sdcc unzip wget gettext xsltproc libboost1.55-dev libboost1.55-tools-dev libxml-parser-perl libusb-dev bin86 bcc bzr ecj sharutils openjdk-7-jdk zip gcc-multilib quilt
// Ubuntu 14.04 可选
# apt-get install subversion mercurial cvs
// ArchLinux 必选
# pacman -S base-devel
# pacman -S [--needed] asciidoc b43-fwcutter bash bc bin86 boost binutils bzip2 cdrkit fastjar flex gawk gettext git gtk2 intltool jdk7-openjdk libusb libxslt ncurses openssl patch perl python2 rsync ruby sdcc sharutils unzip util-linux wget zlib gcc make perl-extutils-makemaker findutils
// 根据wiki,ArchLinux部分必选包在AUR里面
$ yaourt -S bcc jikes
// ArchLinux 可选
# pacman -S subversion

首次配置需要检出源代码,这里用subversion检出开发trunk分支

$ svn co svn://svn.openwrt.org/openwrt/trunk/

这时,就会出现名为trunk的文件夹,这就是将来我们的工作目录。
如果已经有了以前的版本库,需要按照下面的命令更新

// 必须进入工作目录才能更新
$ cd trunk/
$ svn update

更新和安装feeds(需要VPN)

在下载之前可以通过查看feeds.conf.default文件,来检查哪些文件需要包含在环境中。更新只需要重复命令即可

$ cd trunk/
$ ./scripts/feeds update -a
$ ./scripts/feeds install -a

配置编译信息

必须先选择好目标(target)类型才能执行 make defconfig

$ make defconfig
$ make prereq
$ make menuconfig

其中斜线(/)可以进行搜索。
刚开始可以考虑选择编译SDK用于开发,编译ImageGenerator(a.k.a ImageBuilder)简单打包自己需要的Package和配置文件进入固件中,也可以同时打包好工具链(ToolChain)方便以后使用,这样的话时间会稍微长一些。

开始编译

一般情况,进行全部编译时使用一个简单的命令,因为编译过程会下载很多文件,目前许多项目的repo都迁移到GitHub上了,一般情况下不必使用VPN,但是如果网络条件很差,可以考虑使用一个靠谱的VPN服务提供商。

// 一般加上 V=99 来观察错误信息
$ make

编译一个单独的软件包(例如在cups软件包)

$ make package/cups/compile V=99

如果特殊原因需要分析编译报错信息:

$ make V=99 2>&1 |tee build.log |grep -i error

则将编译的所有输出信息保存在build.log中,将error信息打印在屏幕上。

编译结束

编译结束后,所有的文件都会放在编译根目录下的 bin/yourtarget/ ,例如 /bin/ar71xx

$ ls bin/*

编译之后的文件主要有以下几类:

  1. bin/.trx 文件: 路由器固件。如果没有另外一种也不必惊慌。关于.bin和.trx的区别,一种说法是,第一次刷路由器的时候,需要用.bin文件,如果需要再升级,则不能再使用 .bin文件,而需要用 .trx文件。原因是 .bin是将路由器的相关配置信息和 .trx封装在一起而生成的封包,也就是说是包含路由器版本信息的 .trx 在第一次刷固件的时候,我们需要提供这样的信息,而在后续升级时则不再需要,用 .trx文件即可。
  2. packages文件夹: 里面包含了我们在配置文件里设定的所有编译好的软件包。
  3. (可选)OpenWrt-SDK.**.tar.bz2: 这个也就是我们定制编译好的OpenWRT SDK环境。我们将用这个来进行OpenWrt软件包的开发。我的 TP-Link WR841N v7 编译的SDK文件名是OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2
  4. (可选)OpenWrt-ImageBuilder-**.tar.bz2: 这个可以简单打包自己需要的Package和配置文件进入固件中。我的文件名为OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64.tar.bz2
  5. (可选)OpenWrt-Toolchain-**.tar.bz2: 这个是交叉编译工具链。我的是OpenWrt-Toolchain-ar71xx-for-mips_34kc-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2
  6. md5sums 文件: 这个文件记录了所有我们编译好的文件的MD5值,来保证文件的完整性。

编译完成后,一定要将编译好的bin目录进行备份

清理以及再编译

建议现在清理编译产生的文件,以免下次编译时造成冲突,也就是每次编译完成之后把需要的东西复制到别处,然后立即清理(因为要生成的文件如果存在的话,可能不会被替换),执行make clean

注意:在执行clean命令,确保已经将编译好的Image进行了备份。清理工作会清除bin目录。

$ make clean

除了清除生成的目录,还想清除交叉编译工具(以及工具链目录)

$ make dirclean

清除所有相关的东西,包括下载的软件包,配置文件,feed内容等(不建议使用)

$ make distclean

对于更新feeds后出现的错误:ERROR:please fix package/feeds/packages/mc/Makefile 等类似的问题,需要执行这条语句进行系统的清理

对于清理组件,比如软件包的清理

比如清理 linux

$ make target/linux/clean

清理 base-files 软件包

$ make package/base-files/clean

清理 Luci

$ make package/luci/clean

和官方仓库保持同步

很多时候,我们在自己的某个Repository里面进行修改或者开发操作,所以要保证我们的代码与官方的代码保持同步。

官方仓库的地址是 git://git.openwrt.org/openwrt.git 或者 http://git.openwrt.org/openwrt.git。其他在GitHub上的仓库貌似都是镜像,比如openwrt-es以及openwrt-mirror

如果还没进行过多少修改的代码,可以直接fork给出的repo,然后可以方便的使用github本身看我们的分支和官方的代码有多少的超前和滞后提交,可以作为一个提醒。

接下来,我们建立一个远程仓库名为upstream

$ git remote -v   // 首先列出远程仓库,一般只有一个origin

$ git remote add upstream http://git.openwrt.org/openwrt.git

这样就建立好了,我们可以接着列出远程仓库看一下.如果需要变更或者删除远程仓库的话,请参考git remote的manpage.

有的人喜欢使用git pull,但是官方推荐的是使用fetch然后merge,这样有什么区别还有冲突都一目了然.

$ git fetch upstream    // 从官方拉下来最新代码

$ git checkout master   // 切换到主分支,或者是切换到你需要merge到的分支

$ git merge upstream/master // 自动merge进上面切换到的分支中,可以自动或者手动解决冲突

这样,我们就能时刻和官方保持一致了.

OpenWRT 编译 doc 文件

在 OpenWrt 的 trunk 分支中有一个文件夹名为 doc,在这个文件夹中包含一部分文档可供参考,是用 LaTeX 写的,我们需要编译之后才能阅读的更顺畅,编译之后默认生成 .pdf 和 .htm 文件。

在 Ubuntu 我们可以使用 apt-get 从网络上直接下载包来安装。

我们用到的三个比较重要的命令有 apt-cache searchapt-cache show sudo apt-get install

首先使用

$ apt-cache search latex

我们可以看到许多包被列出。选择安装texlive-latex-base, 它的描述是:Tex Live: Basic LaTex packages

sudo apt-get install texlive-latex-base

这样就安装好Latex了,可以直接使用。 但编译中文时,由于没有安装CJK中文环境,会提示找不到CJK包。

$ apt-cache search cjk

选择安装latex-cjk-all, 它的描述是:Installs all LaTex CJK packages.

sudo apt-get install latex-cjk-all 

这样就可以使用中文环境了。

有些.sty文件可能没有安装,例如:lastpage.sty. 这个时候不要到网络上去询问是因为什么, Latex的输出错误信息已经很明显了。使用下面的命令来查找相应的包。注意不要加.sty文件后缀

$ apt-cache search lastpage

可以看到需要下面的包,以及对这个包的描述:texlive-latex-extra - TeX Live: LaTeX supplementary packages 选择安装即可:

sudo apt-get install texlive-latex-extra

完成上面的这三步,就可以基本满足平时的应用需求了。如果以后需要使用新的包,可以使用上面的方法来查找相应的安装包,并选择安装即可。

增加设备支持

前提

如果是专业搞过嵌入式开发的,懂得架构以及其他必要知识的可以忽略这个前提,接下来就是我要说的了,找一款和你想要添加的设备很相近且官方已经有了支持的型号,至少要是相同的平台,比如ar71xx.这部分基本上围绕这个前提来展开。

所需

完整 OpenWrt 开发环境. 包括编辑器, 配置好的 quilt 工具.

假设之前已经编译过 bin, 有完整的 .config 和 toolchain.

目前看到的很多教程教人直接修改现有的 patch 文件或者是 tmp/ 文件夹下的文件,更甚者胡乱猜测,这样会导致一些问题。

比如源码更新的时候,许多 Patch 文件的偏移(offset)会发生变更,主要体现在 linux 内核版本升级的时候,这样直接修改现成的 Patch 就会增添许多烦恼,其实官方有一个很好的东东,那就是这个 quilt,它是用来管理代码树中的 patch 的嵌入式内核开发利器!

增加 Device-Specific 支持文件

这个部分的文件是单独的,与其他的文件比如各种 Patch 没有较大的关联,在重新编译之前只需要make clean就行。

我们以添加 TP-Link TL-WR2041N v1 版本为例子进行说明:

新手刚开始添加支持的时候最好在取出最新的 trunk 代码之后立即进行,防止其他文件干扰,如果之前做过类似的操作或者懂得目录结构、知道文件是做什么用的,可以忽略这个建议。

删除 tmp/ 目录,这个是大坑,因为这个文件夹内的内容全是生成的,没必要进行更改。

$ rm -rvf tmp/

首先,如同前文所述,确定好相近的型号,方便添加支持。我这个型号的板子与国外的 WDR3500 相似,与国内的 TP-Link TL-WR941N v6 相同,我是通过 WDR3500 进行添加的。

搜索以下相关的文件,以确定需要修改什么文件,之后照猫画虎。

运行 grep wdr3500 trunk/* -r -l 得到的结果如下,我已经做好了分类:

// 这部分是Device-Specific的
trunk/target/linux/ar71xx/base-files/etc/diag.sh
trunk/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
trunk/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
trunk/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
trunk/target/linux/ar71xx/base-files/lib/ar71xx.sh
trunk/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr3500.c
// 这部分是制作镜像的相关文件
trunk/target/linux/ar71xx/image/Makefile
trunk/target/linux/ar71xx/generic/profiles/tp-link.mk
trunk/tools/firmware-utils/src/mktplinkfw.c
// 这部分是内核支持相关的文件
trunk/target/linux/ar71xx/config-3.10
trunk/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch

得到的文件就是基本的支持文件了,我们一个一个说。

diag.sh

这个文件是 openwrt 初始化时闪烁的灯的配置,一般的路由启动的时候只闪烁 System 灯或者电源灯,基本没有修改的价值,仿照修改即可。

比如2041n v1:

    tl-wdr3500 | \
    tl-wr2041n-v1 | \
    ........
    tl-wr941nd)
        status_led="tp-link:green:system"

添加到该位置就行。

uci-defaults/01_leds

这个文件是定义 led 的信息的,简单的比如 ucidef_set_led_netdev 多用于定义 WAN 口,修改最后的 eth0 为你对应的设备名称;ucidef_set_led_wlan 多用于定义 WLAN 口,最后的 phyxtpt 目前见到的只有 x=0 和1两种情况,这个和设备初始出来的phy物理设备相关;ucidef_set_led_switch 用来定义交换机的配置,最后的 0x00 部分是端口掩码,一般的顺序如下。

至于更详细的定义过程,需要参考 packages/base-files/files/lib/functions 目录的 uci-defaults.sh 脚本。(目前新加的文件 uci-defaults-new.sh 文件,看样子是通过 JSON 传值的,应该是应用于新的设备或者新的架构的)

比如2041n v1:

tl-wr2041n-v1)
    ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth0"
    ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x02"
    ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x04"
    ucidef_set_led_switch "lan3" "LAN3" "tp-link:green:lan3" "switch0" "0x08"
    ucidef_set_led_switch "lan4" "LAN4" "tp-link:green:lan4" "switch0" "0x10"
    ucidef_set_led_netdev "wlan" "WLAN" "tp-link:green:wlan" "wlan0"
    ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy1tpt"
    ;;
uci-defaults/02_network

该文件定义初始化网络信息,主要是交换机和 vlan,不过我遇到怪异的事情是,ucidef_set_interfaces_lan_wan 紧跟着的第一个参数是定义 wan 的,第二个是定义 lan 的,比如下面的 eth0 是 wan 而 eth1 是 lan 。(貌似是在设备 mach 文件中定义的问题,看了一下网络初始化的脚本uci-defaults.sh 中的定义,应该第一个参数是 lan ,第二个是 wan)比如 wr2041n v1:

tl-wr2041n-v1)
    ucidef_set_interfaces_lan_wan "eth0" "eth1"
    ucidef_add_switch "switch0" "1" "1"
    ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 4"
    ;;
lib/upgrade/platform.sh

该文件是定义系统更新时验证的,基本上不用怎么更改。

比如 2041n v1:

    tl-wdr3500 | \
    tl-wr2041n-v1 | \

添加到了wdr3500的下方。

lib/ar71xx.sh

第一个是硬件 magic number,可以用 WinHex 打开固件文件,查看对应的偏移即可找到,model 定义的是显示的设备名称,下面的 *"TL-WR2041N v1" 要对应设备支持的 mach C语言设备文件中定义好的名称;同样的, name 定义的是内部传递的值,最好与上面添加的行一致。简单来说,涉及到型号名称的最好都保持一致。

比如 2041n v1:

        "204100"*)
        model="TP-Link TL-WR2041N"
        ;;

    *"TL-WR2041N v1")
        name="tl-wr2041n-v1"
        ;;
files/arch/mips/ath79/mach-tl-wdr3500.c

这个就是很重要的设备支持 C语言文件了,开头的前缀 mach 最好保留,mach后的名称需要与以后添加的linux patch支持名称保持一致。

一般用于定义 led、flash 以及 PHY4 等等涉及到的端口信息,有的mach文件还涉及到 ART 的偏移量(offset),ART是存储无线数据的分区,如果设置不当会导致路由没有无线。

为了最快的添加路由支持,可以采用sed, awk工具批量改名的方法,写出一个设备支持文件来,当然也可以使用 vim, emacs批量完成。

比如 2041n v1:新建文件 target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr2041n-v1.c,详情请戳这里

值得注意的是:MIPS_MACHINE(ATH79_MACH_TL_WR2041N_V1, "TL-WR2041N-v1", "TP-LINK TL-WR2041N v1", wr2041n_setup);第一部分要与config-3.10 文件中添加的内容以及后面添加的linux kernel patch中的内容一致;"TL-WR2041N-v1" 是定义的设备名称,最好与 image 的 Makefile一致;"TP-LINK TL-WR2041N v1" 与前面涉及到的lib/ar71xx.sh 文件相关;最后的 wr2041n_setup 是设备初始化的主函数名称。

镜像生成的相关文件
trunk/target/linux/ar71xx/image/Makefile

该文件主要修改如下两行,剩下的内容需要仔细学习 Makefile的写法才能看懂。

$(eval $(call MultiProfile,TLWR2041,TLWR2041NV1))

该行定义多Profile,一般是一个型号生成多个硬件版本支持的定义

$(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWR2041NV1,tl-wr2041n-v1,TL-WR2041N-v1,ttyS0,115200,0x20410001,1,4Mlzma))

该行是单独设备的支持信息,第一个参数是使用什么生成办法,2041n v1是使用 TPLINK-LZMA 方法,前面有对应的说明,从里面也可以看到我们需要修改 bin/mktplinkfw 文件的源代码,该源代码在trunk/tools/firmware-utils/src/mktplinkfw.c 中 接下来可以根据对 TPLINK-LZMA 的定义看到依次传进去的参数,TLWR2041NV1 是 Profile 名称,tl-wr2041n-v1 是生成的镜像名称,也(可能)是传进去的设备型号,TL-WR2041N-v1 最好对应前面 mach 文件 MIPS_MACHINE 函数的信息,主要是在内核日志和系统日志中体现设备型号,后面的是默认 tty 信息以及 baudrate 波特率,接下来的 magic number是设备的硬件ID,1 是版本,一般不用变,4Mlzma是生成固件的layout信息,该值和硬件ID都在 mktplinkfw.c 中定义。

trunk/target/linux/ar71xx/generic/profiles/tp-link.mk

该文件定义 Profile 信息,主要定义 NAME,会显示在 make menuconfig 之后的设备选项里; PACKAGES 定义默认编译安装的包,一般是网卡驱动以及其他必备的包,如 usb支持。

比如 2041n v1:

define Profile/TLWR2041
    NAME:=TP-LINK TL-WR2041N
    PACKAGES:=
endef

define Profile/TLWR2041/Description
    Package set optimized for the TP-LINK TL-WR2041N.
endef
$(eval $(call Profile,TLWR2041))
trunk/tools/firmware-utils/src/mktplinkfw.c

该文件是生成固件文件的工具,里面包含 TP-LINK 固件 bin 文件的结构和 md5 hash 验证算法,比如定义硬件 magic number,flash layout, 以及其他信息。

比如 2041n v1:

#define HWID_TL_WR2041N_V1  0x20410001   //定义硬件ID

{
        .id     = "TL-WR2041Nv1",
        .hw_id      = HWID_TL_WR2041N_V1,
        .hw_rev     = 1,
        .layout_id  = "4Mlzma",
},

定义使用的信息。

config-3.10

添加内核支持的 config 信息,与其他的保持一致就好。

比如 2041n v1:

CONFIG_ATH79_MACH_TL_WR2041N_V1=y

CONFIG_ 后面的内容和上面 mach 硬件支持文件中定义的保持一致。

patches-3.10/610-MIPS-ath79-openwrt-machines.patch

这个是内核支持的patch文件,需要使用 quilt 创建以及以后维护,前一阵子trunk将大部分分散的补丁都移动到这个patch中了,如果要将patch提交到官方尽量放在这里,自己用的话不要干扰其他patch的应用就可以了。我这里将补丁编号为920,一般来说是最后一个应用的patch了。

管理补丁文件

请通过软件包管理器安装 quilt,当然一般如同上文配置好编译环境就已经安装好了 quilt。

然后写入以下配置文件到 ~/.quiltrc

cat > ~/.quiltrc <<EOF
QUILT_DIFF_ARGS="--no-timestamps --no-index -pab --color=auto"
QUILT_REFRESH_ARGS="--no-timestamps --no-index -pab"
QUILT_PATCH_OPTS="--unified"
QUILT_DIFF_OPTS="-p"
EDITOR="nano"
EOF

接着进行一下 export EDITOR ,当然这个 EDITOR 的变量不要和现有的变量冲突,可以自己任意更改,只要应用到上面的.quiltrc 文件中就好了。如果怕麻烦可以写到 ~/.bashrc 文件中,以后就比较方便,不用每次进行 export。

常用的quilt命令如下,会一一说明。

new     新建空白patch
add     添加要修改的文件到patch中
remove      删除patch
top     查看当前patch位置,相当于一个指针
next        未知
rename      重命名patch
unapplied   查看未成功应用的patch
applied     查看已经成功应用的patch
graph       未知
patches     未知
upgrade     未知
delete      删除patch
grep        应该类似于 grep 命令
pop     去往上一个patch,如果附加patch名称则按照patch序列一直应用到特定的patch位置
series      查看patch列表,一般这个顺序就是patch应用的顺序,可以用来进行 pop 和 push 定位
diff        查看区别
previous    未知
edit        编辑当前patch中的文件
push        去往最新的patch,会一直应用到最后一个可以成功应用的patch
files       查看patch中包含的修改文件
refresh     刷新patch,相当于保存patch到 patches 文件夹,还没有应用到buildroot处
几种管理操作
增加一个新的Patch

为一个现有的软件包添加一个新的 Patch 需要首先准备代码树:

$ make package/example/{clean,prepare} V=s QUILT=1

如果是 host-side 的软件包需要进行下面的代码树准备操作:

$ make package/example/host/{clean,prepare} V=s QUILT=1

这个步骤将解压源码包的 tarball 并且按照预先排好的 quilt patch 顺序进行准备工作(简单的讲,按照补丁文件前面的序号给 tarball 依次打好补丁),接下来会输出详细的打补丁情况,如果有未成功的会有 Hunk fail 字样;补丁应用成功的话也有两种情况,第一,行号偏移正常,这也就是我们期望的,第二,虽然应用成功了,但是存在代码行号偏移,出现的字样是 offset ,并且会提示补丁具体应用到了哪行,我们可以针对打补丁时给出的提示修改补丁文件的行号,也可以通过 quilt 修改.

接下来切换到代码目录中,值得注意的是,如果在 Makefile 中存在多个编译选项(build variants),需要切换到对应的代码目录中.

$ cd build_dir/target-*/BUILD_VARIANT/example-*

接下来应用全部的已存在的补丁文件:

$ quilt push -a

通过 quilt new 命令创建一个全新空白的补丁文件:

$ quilt new 010-main_code_fix.patch

命名的时候需要注意的是,补丁文件的名字必须以数字开头,一般是三位,并且补足前面的零,数字之后紧跟一个短横线(-),接下来简单描述这个补丁文件是做什么用的,以便以后好查找;选定数字的时候,数字必须大于现有的最后一个 patch 的数字前缀,这个要求的原因可以通过quilt series 来验证,排序的顺序就是补丁应用的顺序,而排序是通过前面的数字决定的;对补丁文件的描述要言简意赅,尽量用地道的英文术语.

创建好空白的补丁文件之后,必须要有修改的代码文件与之相关联,我们通过 quilt add 来进行这个操作,一旦添加好了文件,就像往常一样进行修改就可以了.可以通过quilt edit 命令来同时完成上面的关联文件操作以及修改操作,这个修改过程调用的文本编辑器是前面在 .quiltrc 文件里面定义好的EDITOR 变量,注意export.

$ quilt edit src/main.c  // 通过quilt的edit命令编辑代码文件

这样上面的代码文件就被加到这个新建的 patch 中了,这样一直重复操作,直到所有需要添加到该 patch 中的文件都修改完.

所有的修改操作都进行完之后,可以通过 quilt diff 命令查看修改的内容.

$ quilt diff          // 很类似 git diff 不是吗

如果发现修改都处于预期,就可以把修改写入到刚才新建的patch文件中了,注意这时候的patch还在 build_dir 里面.

$ quilt refresh

接下来切换到 buildroot 的顶层目录.

$ cd ../../../      // 这个目录比修改 kernel 补丁时低了一层

接下来,我们将刚才新建的 patch 移动到 buildroot ,这样我们就可以将这个补丁进行提交等其他操作了.

$ make package/example/update V=s

这样,我们的补丁添加工作就完成了,不放心的话可以通过下面的命令进行验证:

$ make package/example/{clean,compile} package/index V=s

如果发现问题,需要重新进行编辑,下面介绍怎么编辑补丁文件.

编辑一个现有的patch

还是需要首先准备代码树:

$ make package/example/{clean,prepare} V=s QUILT=1

接下来切换到代码目录中.

$ cd build_dir/target-*/example-*

列出现有的所有patch文件:

$ quilt series

前往需要编辑的patch文件,当然前提是这个push到的patch需要应用成功,否则需要push到提前一个patch,当然这个是后话.

$ quilt push 010-main_code_fix.patch

当输入的patch文件名合法的话,quilt push 命令会只应用patch 系列(patch series)到给出的文件名,所以提前用quilt series 命令看好文件名再操作,然后用 quilt top 命令看自己当前处于哪个patch中确保万无一失,如果不幸超过了所要去的补丁位置,可以通过quilt pop 命令移除已经应用的补丁按照列表反向前进.

接下来通过 quilt edit 命令编辑每个需要编辑的文件.

$ quilt edit src/main.c    // 熟悉的命令

接下来检查编辑的文件是否被包含在patch中了:

$ quilt files

检查更改信息:

$ quilt diff

如果发现修改都处于预期,就可以把修改写入patch文件中了,注意这时候的patch还在 build_dir 里面.

$ quilt refresh

切换到buildroot的顶层目录中.

$ cd ../../../

接下来,我们将刚才更新好的patch移动到buildroot中:

$ make package/example/update V=s

这样,我们的补丁修改工作就完成了,不放心的话可以通过下面的命令进行验证:

$ make package/example/{clean,compile} package/index V=s
新增或修改内核补丁

新增和修改内核补丁和操作安装包的补丁差不太多,只有 make 的 target 和操作代码目录是不同的.

特别需要注意的是,对于内核补丁,存在一个附加的子目录,一个是 generic/ 目录,这个里面包含对所有目标架构的补丁文件;另一个是 platform/ 目录,这里面包含特定架构的补丁文件,一般是在make menuconfig 中配置好的架构,也可以在 .config 文件中找到.

准备内核代码树:

$ make target/linux/{clean,prepare} V=s QUILT=1

对稳定版AA(Attitude Adjustment)来说,内核代码树在这里:

$ cd build_dir/linux-*/linux-3.*

对主干分支,现在是BB(Barrier Breaker),代码树在这里:

$ cd build_dir/target-*/linux-*/linux-3.*

我们将刚才操作好的patch移动到buildroot中通过下面的命令:

$ make target/linux/update package/index V=s

注意:Patch文件的前缀必须正确,指明是 generic 还是 platform,如果前缀不正确,可能应用操作会出问题.

不放心的话可以通过下面的命令进行验证,首先去顶层目录,一般是 target/ 所在的目录:

$ cd ../../../../

然后再次准备代码树,查看更改是否已经应用了:

$ make target/linux/{clean,prepare} V=s QUILT=1

最后要说的是,放置patch的位置很重要,它决定补丁的应用情况.

增加或编辑工具链 Patch(这部分一般不会涉及)

以 gcc 为例:

准备工具链代码树:

$ make toolchain/gcc/{clean,prepare} V=99 QUILT=1

代码树路径取决于选择的库以及 gcc :

$ cd build_dir/toolchain-mips_r2_gcc-4.3.3+cs_uClibc-0.9.30.1/gcc-4.3.3

通过如下命令更新Patch:

$ make toolchain/gcc/update V=99
刷新Patch

当软件包更新或者内核更新时,现有的patch文件可能不会完全应用或者存在其他提示。想要重新构建Patch列表中的全部patch可以使用make目标:refresh.

$ make package/example/refresh V=s    // 软件包
$ make target/linux/refresh V=s       // 内核
不清理代码树重复修改补丁

当需要引入新功能做更改时,经常需要多次修改补丁。为了加速,可以在编辑操作(edit)之间保留做完准备操作的代码树.

  1. 刚开始如上文所述准备好代码树;
  2. 切换到准备好的代码目录;
  3. 前往需要修改的patch位置;
  4. 修改文件并保存对patch文件的更改;
  5. 通过 quilt push -a 命令完全应用剩下的补丁文件;
  6. 切换到顶层目录运行 make package/example/{compile,install} ,如果是内核的补丁,使用 make target/linux/{compile,install} 命令;
  7. 测试二进制文件。如果再次需要进行更改,从第二步重复操作;
  8. 最后使用 make package/example/update 命令 ,如果是内核补丁,使用 make target/linux/update 命令将patch文件应用到buildroot中。
准备 linux 内核 patch

到这里基本就完成了 OpenWrt 的设备支持代码. 为了支持我们的设备, Linux 代码树的部分文件也需要做改动, OpenWrt 采用了 patch 的方式实现.

回退到源代码的根目录 ~/trunk .

清理并准备 patch 树:

$ make target/linux/{clean,prepare} V=s QUILT=1

进入内核代码目录:

$ cd build_dir/target-*/linux-ar71xx_generic/linux-3.x/

这里就是内核代码树了, 里面的代码是已经打过所有 patch 的, 可以用 quilt push 检查看是不是这样:

$ quilt push

File series fully applied, ends at patch platform/xxx-xxxxxxxxxxxxxx.patch.

这条输出也告诉我们, 当前最顶的 patch 是 platform/xxx

为我的 WL-WR2041N v1 新建个 patch:

$ quilt new platform/920-MIPS-ath79-add-TL-WR2041N-v1-support.patch

选择的数字需要大于刚才的那个 xxx , 然后 quilt 会自动把这个 patch 设置为当前 patch, 所有的改动都针对这个 patch.

注意修改文件之前一定要看自己位于哪个patch下,否则修改都会更新到那个patch.

然后就是增加代码了

$ quilt edit arch/mips/ath79/Kconfig
$ quilt edit arch/mips/ath79/Makefile
$ quilt edit arch/mips/ath79/machtypes.h

至于怎么改, 参考这些文件里其他硬件的配置

比如 2041n v1:

--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -900,6 +900,16 @@ config ATH79_MACH_TL_WR1043ND_V2
    select ATH79_DEV_USB
    select ATH79_DEV_WMAC

+config ATH79_MACH_TL_WR2041N_V1
+   bool "TP-LINK TL-WR2041N v1 board support"
+   select SOC_AR934X
+   select ATH79_DEV_AP9X_PCI if PCI
+   select ATH79_DEV_ETH
+   select ATH79_DEV_GPIO_BUTTONS
+   select ATH79_DEV_LEDS_GPIO
+   select ATH79_DEV_M25P80
+   select ATH79_DEV_WMAC
+
 config ATH79_MACH_TL_WR2543N
    bool "TP-LINK TL-WR2543N/ND support"
    select SOC_AR724X
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_ATH79_MACH_TL_WR841N_V9)   +=
 obj-$(CONFIG_ATH79_MACH_TL_WR941ND)    += mach-tl-wr941nd.o
 obj-$(CONFIG_ATH79_MACH_TL_WR1041N_V2) += mach-tl-wr1041n-v2.o
 obj-$(CONFIG_ATH79_MACH_TL_WR1043ND)   += mach-tl-wr1043nd.o
+obj-$(CONFIG_ATH79_MACH_TL_WR2041N_V1) += mach-tl-wr2041n-v1.o
 obj-$(CONFIG_ATH79_MACH_TL_WR1043ND_V2)    += mach-tl-wr1043nd-v2.o
 obj-$(CONFIG_ATH79_MACH_TL_WR2543N)    += mach-tl-wr2543n.o
 obj-$(CONFIG_ATH79_MACH_TL_WR703N) += mach-tl-wr703n.o
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
@@ -134,6 +134,7 @@ enum ath79_mach_type {
    ATH79_MACH_TL_WR1041N_V2,   /* TP-LINK TL-WR1041N v2 */
    ATH79_MACH_TL_WR1043ND,     /* TP-LINK TL-WR1043ND */
    ATH79_MACH_TL_WR1043ND_V2,  /* TP-LINK TL-WR1043ND v2 */
+   ATH79_MACH_TL_WR2041N_V1,       /* TP-LINK TL-WR2041N v1 */
    ATH79_MACH_TL_WR2543N,      /* TP-LINK TL-WR2543N/ND */
    ATH79_MACH_TL_WR703N,       /* TP-LINK TL-WR703N */
    ATH79_MACH_TL_WR710N,       /* TP-LINK TL-WR710N */

仅作为参考。

然后验证下修改的内容:

$ quilt diff # 查看 diff
$ quilt refresh # 保存所有 diff 到 patch 文件

这个时候我们的 patch 文件还在 build_dir 里, 大概位置是 patches/platform/ 下. 需要同步到 OpenWrt 代码树.

退回到顶层工作目录, 执行:

$ make target/linux/update V=s

同步完成后, patch 文件会出现在 target/linux/ar71xx/patches-3.x/ 下.

以后代码更新后需要编辑 patch 时,遵从上面的 quilt 对 patch 的管理操作。

开始编译

再次记得, 删除 tmp 目录

$ rm -rvf tmp/
$ make menuconfig
几个问题解决的案例
参考链接

http://wiki.openwrt.org/doc/devel/add.new.device
http://wiki.openwrt.org/doc/devel/hw.hacking.first.steps
http://wiki.openwrt.org/doc/devel/patches
http://andelf.diandian.com/post/2013-05-22/40050677370
http://tilt.lib.tsinghua.edu.cn/node/841
http://www.openwrt.org.cn/bbs/forum.php?mod=viewthread&tid=211
http://www.tuicool.com/kans/481707042
http://www.openwrt.org.cn/bbs/forum.php?mod=viewthread&tid=60&extra=page%3D1

http://hi.baidu.com/gouooo/item/6932bfa97d23d1981410736a


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值