前言

一般来说要解包固件都很简单,但是要对固件进行修改并重新刷回设备就有一定的难度了。本文研究了几种修改固件并刷回设备的方法。

手动打包固件

拿dcs921l的固件来举例,先用binwalk分析下它的结构:

结构很明显,U-Boot加上uImage头加上lzma打包的内核系统。简单的结构图如下:

ok,结构分析完了,现在可以解包固件做点小修改再进行打包了。解包一条命令搞定:

binwalk -Me dcs932l_v1.14.04.bin

进入文件系统目录,根据自己需要修改文件,打包成cpio压缩文件:

find . | cpio -H newc -o > ../initrd.cpio

再用lzma进行压缩,可在这里下载对应版本的lzma sdk,注意原固件的lzma压缩指定了字典大小,我们需要使用和它一致的字典大小,用-d参数指定字典大小:

./lzma e initrd.cpio initrd.cpio.lzma -d20

截取内核文件系统前的数据再拼接到我们的文件系统前:

dd if=50040 of=kernelHead bs=1 count=4038656
cp ./kernelHead ./kernel
cat initrd.cpio.lzma >> kernel

再对内核进行压缩:

./lzma e ./kernel ./kernel.lzma -d25

截取uImage头拼接到内核压缩文件前:

dd if=dcs of=uImageHeader bs=1 count=64
cp uImageHeader uImage
cat kernel.lzma >> uImage

注意uImage头这里是有CRC验证的,我们需要自己计算一下CRC校验和并修改uImage头的信息。WinHex打开,下图圈起来的几位分别是header CRC,image大小和data CRC:

先计算data CRC,选中uImage头之后的部分,在Tools->Compute Hash中选择CRC32进行计算:

把data CRC修改为我们计算的值,同时填上image大小的值:

之后计算header CRC的值,把原来的值都用00来覆盖再计算就行了:

当然,也有不需要手动改CRC的方法。在ubuntu下安装u-boot-tools,再用mkimage命令就可以自动生成uImage头:

sudo apt-get install u-boot-tools
mkimage -A MIPS -O linux -T kernel -C lzma -a 0x80000000 -e 0x803B8000 -n "Linux Kernel Image" -d kernel.lzma uImage

mkimage各参数信息如下:

-A ==> set architecture to 'arch'     // 用于指定CPU类型
          -O ==> set operating system to 'os'     // 用于指定操作系统
          -T ==> set image type to 'type'      // 用于指定image类型
          -C ==> set compression type 'comp'     // 指定压缩类型
          -a ==> set load address to 'addr' (hex)     // 指定image的加载地址
          -e ==> set entry point to 'ep' (hex)     // 指定内核的入口地址
          -n ==> set image name to 'name'    // image在头结构中的命名
          -d ==> use image data from 'datafile'     // 无头信息的image文件名
          -x ==> set XIP (execute in place)     // 设置执行位置

如果你能通过TTL进设备U-Boot的话固件打包到这一步就行了,如果要通过web界面更新固件就需要再加上前面的一段U-Boot了,这里不再赘述。

烧录固件

启动设备,在串行界面可以看到打印如下信息:

U-Boot 1.1.3

Board: Ralink APSoC DRAM: 32 MB
relocate_code Pointer at: 81fac000
config usb..

Set info->start[0]=BF000000
flash_protect ON: from 0xBF000000 to 0xBF021767
flash_protect ON: from 0xBF030000 to 0xBF030FFF

*** Warning - bad CRC, using default environment
============================================ 

Ralink UBoot Version: 3.5.2.0
-------------------------------------------- 
ASIC 3052_MP2 (Port5<->None)
DRAM component: 256 Mbits SDR
DRAM bus: 16 bit
Total memory: 32 MBytes
Flash component: NOR Flash
============================================ 
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:128, ways:4, linesz:32 ,total:16384 
 ##### The CPU freq = 320 MHZ #### 
 estimate memory size =32 Mbytes

Signature: DCS-930 932L Release 1.11 (2011-05-31)

Please choose the operation: 
   1: Load system code to SDRAM via TFTP. 
   2: Load system code then write to Flash via TFTP. 
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   7: Load Boot Loader code then write to Flash via Serial. 
   9: Load Boot Loader code then write to Flash via TFTP.

这里我们选择1,通过TFTP写入系统固件到内存中,不要刷到flash里,不然刷错固件就凉了。搭建TFTP服务器的过程这里就不赘述了。

1: System Load Linux to SDRAM via TFTP. 
 Please Input new ones /or Ctrl-C to discard
        Input device IP (192.168.1.1) ==:192.168.0.100
        Input server IP (192.168.1.100) ==:192.168.0.103
        Input Linux Kernel filename () ==:uImage

设备从tftp服务器上下载完固件后就会自动启动系统了:

openwrt固件编译

要向设备中刷入openwrt固件需要先去openwrt官网查找是否支持此设备。你可以直接在官网下载支持设备的固件,也可以自己动手编译。
下载源码包

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

安装相应的依赖:

sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip zip unrar p7zip p7zip-rar p7zip-full sharutils subversion libncurses5-dev ncurses-term zlib1g-dev gawk git-core libssl-dev

升级安装扩展软件:

./scripts/feeds update -a
./scripts/feeds install -a
make package/symlinks

使用默认编译环境:

make defconfig

配置:

make menuconfig

选择相应的目标平台,设备芯片型号和设备具体型号等:

编译,Openwrt会帮你把需要的包下载安装好,并生成对应的固件包,一般需要4-5个小时:

make V=99

编译完成后可在./bin/targets/ramips/rt305x/下找到编译好的固件文件,在./build_dir/target-mipsel_24kc_musl/root-ramips目录下有配置好的文件目录系统。

通过u-boot成功刷入设备:

Ralink SDK固件配置编译

dcs932l使用的是Ralink RT3052的主控,我们可以通过编译Ralink SDK来定制自己的固件。

Ralink SDK开发手册以及源码包下载:https://pan.baidu.com/s/1VenLy-YM2f-sTOy-aLkJSw (y9u0)

Tool chain安装配置

复制buildroot源码包到/opt目录下,并解压

cp RT288x_SDK/toolchain/buildroot-gcc342.tar.bz2 /opt
tar jxvf buildroot-gcc342.tar.bz2

编译安装LZMA

tar xvfz RT288x_SDK/toolchain/lzma-4.32.7.tar.gz
cd RT288x_SDK/toolchain/lzma-4.32.7 
./configure 
make 
make install

编译安装MKSQUASHFS

cd RT288x_SDK/toolchain/mksquash_lzma-3.2 
make
make install

另外最好将本机的make版本换成低版本的,不然会出现make无法识别旧版本内核的Makefile语句的问题(当然也可以直接一个个改Makefile,也就那么几句错误)

source配置编译

make menuconfig

Select the Product you wish to target-->选择对应的硬件芯片型号:

Kernel/Library/Defaults Selection --->选择是否配置Kernel,library,busybox,头一次编译可以都选上一次性设置完:

Kernel配置

下面是我的设备需要配置的选项,仅作为参考。

Machine selection --->
    System type--> (选择板子型号)
    DRAM Size (32M) ---> (选择内存大小)
    Kernel NVRAM (启用NVRAM)
    Compress ramdisk by lzma instead of gzip (用lzma打包镜像文件)
General setup --->
    Kernel->user space relay support (formerly relayfs) (启用内核空间到用户空间的relay支持)
Block layer --->
    Enable the block layer (启用通用块层)
    IO Schedulers --->
        Default I/O scheduler (No-op) ---> (默认I/O调度器为No-op *适合闪存设备和嵌入式系统的I/O调度器)
            No-op
Networking --->
    Networking options --->
        Packet socket
        Unix domain sockets(同一主机进程间通信)
        TCP/IP networking
    Generic IEEE 802.11 Networking Stack(无线网络支持)
        IEEE 802.11 WEP encryption (802.1x)
Device Drivers --->
    Network device support --->
        Network device support (启用网络设备支持)
    Character devices --->
        Ralink GPIO Support
            Ralink GPIO LED Support
    USB support --->
        Support for Host-side USB
            USB device filesystem
File systems --->
    Kernel automounter support (内核自动挂载支持)
    Kernel automounter version 4 support (also supports v3)
    Filesystem in Userspace support
    Pseudo filesystems --->
        /proc file system support
            /proc/kcore support
            Sysctl support (/proc/sys)
        sysfs file system support

Library配置

Library Configuration ---> (选择需要的Lib库)
Network Applications ---> (选择需要的网络相关软件)
    storage(enable chmod, fdisk in busybox)
        proftpd (FTP Server)
    iptables
    openssl
    pppd
        l2tp client
    pptp
    uvc_stream
Miscellaneous Applications --->
    busybox
    mtd write
Proprietary Application --->
    NVRAM
    GPIO

其余配置

Busybox Settings --->
    Build Options --->
        Build BusyBox as a static binary (no shared libs) (编译成静态文件)

其他的根据需要进行选择就行了。
uClibc Configuration 和 uClibc++ Configuration基本选默认的就行。

编译

make dep
make

编译完成后可在source/images目录下找到root_uImage镜像文件,在source/romfs下存在文件系统。

Ralink SDK文件系统修改

光编译好固件可不能满足我们的要求,还要能修改启动脚本,添加我们自己的文件才行。
打开source/vendors/Ralink/RT3052目录下的Makefile可以看到它创建了文件目录系统,并把一些需要的文件拷进去了:

那么我们就可以通过修改Makefile和目录下的文件来编辑自己的文件系统。可根据需要修改下面几个文件:

rcS: 启动脚本
inittab: init进程配置文件
motd: Ralink图标
fstab:文件系统信息
RT2860_default_vlan:nvram默认配置文件

在ROMFS_DIRS后添加目录,在$(ROMFSINST) /etc_ro/motd后添加文件(注意这里的文件需要放在source/vendors/Ralink/RT3052目录下):

查看source/user/rt2880_app/scripts目录下的Makefile可以发现它配置了/sbin目录下的可执行文件和脚本文件:

要添加脚本只需复制到source/user/rt2880_app/scripts目录下即可。

启动脚本配置

下面我的启动脚本配置,并进行了注释,仅作为参考:

#!/bin/sh
mount -a #挂载所有的文件系统,在fstab文件中有配置
mkdir -p /var/run
cat /etc_ro/motd

# Linux 2.6 uses udev instead of devfs, we have to create static dev node by myself
# 创建静态dev节点
mounted=`mount | grep mdev | wc -l`
if [ $mounted -eq 0 ]; then
mount -t ramfs mdev /dev
mkdir /dev/pts
mount -t devpts devpts /dev/pts
mdev -s
fi


# 创建设备文件
mknod /dev/spiS0 c 217 0
mknod /dev/i2cM0 c 218 0
mknod /dev/rdm0 c 254 0
mknod /dev/flash0 c 200 0
mknod /dev/swnat0 c 210 0
mknod /dev/hwnat0 c 220 0
mknod /dev/acl0 c 230 0
mknod /dev/ac0 c 240 0
mknod /dev/mtr0 c 250 0
mknod /dev/nvram c 251 0
mknod /dev/gpio c 252 0
mknod /dev/PCM c 233 0
mknod /dev/I2S c 234 0

echo "# <device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]" > /etc/mdev.conf
echo "# The special characters have the meaning:" >> /etc/mdev.conf
echo "# @ Run after creating the device." >> /etc/mdev.conf
echo "# $ Run before removing the device." >> /etc/mdev.conf
echo "# * Run both after creating and before removing the device." >> /etc/mdev.conf
echo "sd[a-z][1-9] 0:0 0660 */sbin/automount.sh \$MDEV" >> /etc/mdev.conf

#enable usb hot-plug feature
echo "/sbin/mdev" > /proc/sys/kernel/hotplug

# 启动nvram_daemon进程
nvram_daemon&

# 从nvram配置文件中获取用户名和密码并设置系统用户
login=`nvram_get 2860 Login`
pass=`nvram_get 2860 Password`
echo "$login::0:0:Adminstrator:/:/bin/sh" > /etc/passwd
echo "$login:x:0:$login" > /etc/group
chpasswd.sh $login $pass

# audio
pcmcmd -s &

# video
uvc_stream -b &

sleep 2

# Set RT3050 to dump switch mode (restore to no VLAN partition)
switch reg w 14 5555
switch reg w 40 1001
switch reg w 44 1001
switch reg w 48 1001
switch reg w 4c 1
switch reg w 50 2001
switch reg w 70 ffffffff
switch reg w 98 7f7f
switch reg w e4 7f

lan_if="br0"
# lo interface up -- mydlink need it
ifconfig lo up

# setup bridge, lan and wlan interface, and fast forwarding time (setfd, setmaxage)
ifconfig eth2 0.0.0.0
ifconfig ra0 0.0.0.0

brctl addbr br0
brctl addif br0 ra0
brctl addif br0 eth2

brctl setfd br0 1
brctl setmaxage br0 1 

# setup wlan enable/disable
gpio wlan 1

# 配置ip地址
ip=`nvram_get 2860 wan_ipaddr`
nm=`nvram_get 2860 wan_netmask`
gw=`nvram_get 2860 wan_gateway`

ifconfig $lan_if $ip netmask $nm
route del default
gpio gw 0.0.0.0
if [ "$gw" == "0.0.0.0" ]; then
gw=""
fi
if [ "$gw" != "" ]; then
route add default gw $gw
gpio gw $gw
else
route add default gw $ip
fi

# 后台启动alphapd服务
web.sh

sleep 3

# 后台运行调度器
killall -q schedule
schedule &

#for telnet debugging
telnetd

#for syslogd
mkdir -p /var/log

点击收藏 | 1 关注 | 1
登录 后跟帖